Python描述符(descriptor)

Python 描述符(descriptor) Python 中有一个很少被使用或者用户自定义的特性,那就是描述符(descriptor),但它是@property, @classmethod, @staticmethod和super的底层实现机制,我今天就扒一扒它,官方文档对描述符的介绍如下 In general, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol: __get__(), __set__(), and __delete__(). If any of those methods are defined for an object, it is said to be a descriptor. 描述符是绑定了行为的对象属性(object attribute),实现了描述符协议(descriptor protocol),描述符协议就是定义了__get__(),__set__(),__delete__()中的一个或者多个方法,将描述符对象作为其他对象的属性进行访问时,就会产生一些特殊的效果。 上面的定义可能还是有些晦涩,一步步来 默认查找属性 在没有描述符定义情况下,我们访问属性的顺序如下,以a.x为例 查找实例字典里的属性就是a.__dict__['x']有就返回 往上查找父类的字典就是a.__class__.__dict__['x']有就返回 上面都没有就查找父类的基类(不包括元类(metaclass)) 如果定义了__getattr__就会返回此方法 最后都没有抛出AttributeError >>> class A: ... x = 8 ... ... >>> class B(A): ... pass ... >>> class C(B): ... def __getattr__(self, name): ... if name == 'y': ... print("call getattr method") ... else: ... raise AttributeError ... ... ... >>> C.__mro__ (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) >>> a = C() >>> a.x 8 >>> a.y call getattr method >>> a.__dict__ {} >>> a.x = 99 >>> a.x 99 >>> a.__dict__ {'x': 99} __getattr__是实例访问没有定义的属性时调用的方法,需要特别定义 ...

December 17, 2019 · 6 min · 1135 words · Fython

使用 Core dump 解密加密的sh脚本

使用 Core dump 解密加密的脚本 之前遇到网上的集成的shell脚本有点问题想手动修改下,发现脚本是加密的,网上找了好久发现有gzexe、shc加密方法都尝试了一遍,可惜解密都不成功,最后用了一个粗暴的办法就是任何程序总要加载到内存运行的吧,那就直接中断coredump查看内存里的内容,以下是具体方法。 root用户执行如下命令 ulimit -c unlimited echo "/core_dump/%e-%p-%t.core" > /proc/sys/kernel/core_pattern mkdir /core_dump 以上第一句是设置内核coredump大小,这里设置不限制。第二句是设置coredump存储位置和格式,%e代表可执行程序名,%p代表pid, %t代表生成时间。然后去执行脚本如xxx.sh ./xxx.sh 6 start & (sleep 0.01 && kill -SIGSEGV $!) 之后会输出类似[1]+ Segmentation fault (core dumped)...的提示,然后查看/core_dump文件夹下,就会有dump出来的文件了,直接vim打开查看会有一些乱码手动处理一下就可以了。 如果在core_dump文件夹下没有dump出来的文件,可使用如下命令测试然后查看是否有文件生成。 sleep 15 & killall -SIGSEGV sleep 正常情况下core_dump文件夹下会有以sleep开头的文件。

October 16, 2019 · 1 min · 40 words · Fython

Python实现单例(Singleton)的几种方法

Python实现单例(Singleton)的几种方法 单例是一种比较简单的设计模式,每次实例化只提供一个相同的实例对象,对于保证实例唯一和节约系统资源的时候十分有用,下面就看看python中实现单例的几种方法 使用__new__方法 因为在类的实例化过程中__new__方法会比__init__提前调用,我们在类属性中保存一个_singleton每次只返回这个。 class Singleton: def __new__(cls, *args, **kwargs): if not getattr(cls, '_singleton', None): cls._singleton = super().__new__(cls, *args, **kwargs) return cls._singleton class MyClass(Singleton): pass a = MyClass() b = MyClass() print(id(a)) # 4433117872 print(id(b)) # 4433117872 print(a is b) # True 使用装饰器 from functools import wraps def singleton(cls): _singleton = {} @wraps(cls) def wrapper(*args, **kwargs): if not _singleton.get(cls): _singleton[cls] = cls(*args, **kwargs) return _singleton[cls] return wrapper @singleton class MyClass: pass 利用装饰器中的_singleton变量存储所有类的实例 利用python模块 python模块(module)是天然的单例模式 # singleton.py class Singleton: def foo(self): print("I'm singleton") instance = Singleton() del Singleton 然后利用模块导入 from single import instance instance.foo() # I'm singleton

February 27, 2019 · 1 min · 96 words · Fython

Mac不安装第三方应用读写NTFS格式硬盘

Mac不安装第三方应用读写NTFS格式硬盘 首先插入硬盘或者U盘,现在的盘只能读取,我们先umount以/dev/disk3s2分区为例 ❯ mount # 列出挂载分区 /dev/disk1s5 on / (apfs, local, read-only, journaled) devfs on /dev (devfs, local, nobrowse) /dev/disk1s1 on /System/Volumes/Data (apfs, local, journaled, nobrowse) /dev/disk1s4 on /private/var/vm (apfs, local, journaled, nobrowse) /dev/disk3s2 on /Volumes/TOSHIBA EXT (ntfs, local, nodev, nosuid, read-only, noowners) ❯ sudo umount /Volumes/TOSHIBA\ EXT 创建挂在路径,然后手动挂载 sudo mkdir /Volumes/mount sudo mount -t ntfs -o rw,auto,nobrowse /dev/disk3s2 /Volumes/mount cd /Volumes/mount 就这样移动硬盘可读写了,也可以打开Finder试试

January 25, 2019 · 1 min · 63 words · Fython

Mysql数据库备份脚本(使用mysqldump)

Mysql(mysqldump)备份脚本 记录下服务器上一个备份 mysql 数据库的脚本,使用 mysql 自带的mysqldump命令 !/usr/bin/env bash USER=username PASSWORD=password MAXIMUM_BACKUP_FILES=10 BACKUP_FOLDER=/path/to/save/folder DATABASES=( db_name_0 db_name_1 ) # check mysqldump instlled _=$(command -v mysqldump) if [[ $? != 0 ]] then printf "You don't seem to mysqldump installed, exit..\n" exit 1 fi # create backup folder if [ ! -d $BACKUP_FOLDER ] then mkdir $BACKUP_FOLDER fi # backup for DB in ${DATABASES[@]} do echo backing up ${DB} database ... if $(mysqldump --host=localhost --user=${USER} --password=${PASSWORD} ${DB} | gzip -9 > ${BACKUP_FOLDER}/db_${DB}_$(date +"%Y%m%d").sql.gz) then echo dump db_${DB}_$(date +"%Y%m%d").sql.gz done. else echo dump db_${DB}_$(date +"%Y%m%d").sql.gz failed. fi done # remove older files find ${BACKUP_FOLDER} -type f -name *.sql.gz -mtime +${MAXIMUM_BACKUP_FILES} -delete 脚本就是使用 mysqldump 备份指定的数据库(在 DATABASES 使用空格分隔)然后 gzip 压缩保存到指定目录,使用系统自带的 find 命令删除旧文件 ...

November 8, 2018 · 2 min · 260 words · Fython