Python 魔法方法总结

Python 魔法方法

基础:

如果你想... 所以,你写... Python调用...
初始化一个实例 x = MyClass() x.__init__()
作为一个字符串的"官方"表示 repr(x) x.__repr__()
作为一个字符串 str(x) x.__str__()
作为字节数组 bytes(x) x.__bytes__()
作为格式化字符串 format(x, format_spec) x.__format__(format_spec)
  • __init__()方法在创建实例后调用.如果你想控制创建过程,请使用__new__()方法
  • 按照惯例, __repr__() 应该返回一个有效的Python表达式的字符串
  • __str__()方法也被称为你的print(x)

迭代相关

如果你想... 所以,你写... Python调用...
遍历一个序列 iter(seq) seq.__iter__()
从迭代器中获取下一个值 next(seq) seq.__next__()
以相反的顺序创建一个迭代器 reversed(seq) seq.__reversed__()
  • __iter__()无论何时创建新的迭代器,都会调用该方法.
  • __next__()每当你从迭代器中检索一下个值的时候,都会调用该方法
  • __reversed__()方法并不常见.它需要一个现有序列并返回一个迭代器,该序列是倒序的顺序.

属性

如果你想... 所以,你写... Python调用...
得到一个属性 x.my_property x.__getattribute__('my_property')
获得一个属性 x.my_property x.__getattr__('my_property')
设置一个属性 x.my_property = value x.__setattr__('my_property', value)
阐述一个属性 del x.my_property x.__delattr__('my_property')
列出所有属性和方法 dir(x) x.__dir__()
  • 如果你的类定义了一个__getattribute__()方法,Python将在每次引用任何属性或方法名时调用它.
  • 如果你的类定义了一个__getattr__()方法,Python只会在所有普通地方查找属性后调用它.如果一个实例x定义了一个属性 color, x.color将不会调用x.__getattr__('color'); 它将简单地返回已经定义的x.color值.
  • __setattr__()只要你为属性指定值,就会调用该方法.
  • __delattr__()只要删除属性,就会调用该方法.
  • __dir__()如果您定义一个__getattr__() 或者 __getattribute__() 方法,该方法很有用.通常情况下,调用dir(x)只会列出常规属性和方法.

__getattr__()__getattribute__()方法之间的区别很微妙但很重要.

函数类

通过定义call()方法,您可以创建一个可调用类的实例 - 就像函数可调用一样.

如果你想... 所以,你写... Python调用...
来"调用"像函数一样的实例 my_instance() my_instance.__call__()

行为

如果你的类作为一组值的容器 - 也就是说,如果问你的类是否"包含"一个值是有意义的 - 那么它应该定义下面的特殊方法,使它像一个集合一样.

如果你想... 所以,你写... Python调用...
序列的数量 len(s) s.__len__()
否包含特定的值 x in s s.__contains__(s)

字典(映射)

如果你想... 所以,你写... Python调用...
通过它的key来获得值 x[key] x.__getitem__(key)
通过它的key来设置一个值 x[key] = value x.__setitem__(key, value)
删除键值对 del x[key] x.__delitem__(key)
为丢失的key提供默认值 x[nonexistent_key] x.__missing__(nonexistent_key)

数字

如果你想... 所以,你写... Python调用...
x + y x.__add__(y)
x - y x.__sub__(y)
x * y x.__mul__(y)
整除 x / y x.__trueiv__(y)
x // y x.__floordiv__(v)
取余 x % y x.__mod__(y)
整除与取余 divmod(x, y) x.__divmod__(y)
平方 x ** y x.__pow__(y)
左移 x << y x.__lshift__(y)
友移 x >> y x.__rshift__(y)
按位and运算 x & y x.__and__(y)
按位xor或运算 x ^ y x.__xor__(y)
按位or运算 `x y` x.__or__(y)

上述一组特殊方法采用第一种方法:给定x / y,它们提供了一种方法让x说"我知道如何用y整除自己".以下一组特殊方法解决了第二种方法:它们为y提供了一种方法来说"我知道如何成为分母,并将自己整除x".

如果你想... 所以,你写... Python调用...
x + y x.__radd__(y)
x - y x.__rsub__(y)
x * y x.__rmul__(y)
整除 x / y x.__rtrueiv__(y)
x // y x.__rfloordiv__(v)
取余 x % y x.__rmod__(y)
整除与取余 divmod(x, y) x.__rdivmod__(y)
平方 x ** y x.__rpow__(y)
左移 x << y x.__rlshift__(y)
友移 x >> y x.__rrshift__(y)
按位and运算 x & y x.__rand__(y)
按位xor或运算 x ^ y x.__rxor__(y)
按位or运算 `x y` x.__ror__(y)

可是等等!还有更多!如果你正在进行"就地"操作,如x /= 3则可以定义更多特殊的方法.

如果你想... 所以,你写... Python调用...
x + y x.__iadd__(y)
x - y x.__isub__(y)
x * y x.__imul__(y)
整除 x / y x.__itrueiv__(y)
x // y x.__ifloordiv__(v)
取余 x % y x.__imod__(y)
整除与取余 divmod(x, y) x.__idivmod__(y)
平方 x ** y x.__ipow__(y)
左移 x << y x.__ilshift__(y)
友移 x >> y x.__irshift__(y)
按位and运算 x & y x.__iand__(y)
按位xor或运算 x ^ y x.__ixor__(y)
按位or运算 `x y` x.__ior__(y)

还有一些"单个数"数学运算可以让你自己对类似数字的对象进行数学运算.

如果你想... 所以,你写... Python调用...
负数 -x x.__neg__()
正数 +x x.__pos__()
绝对值 abs(x) x.__abs__()
~x x.__invert__()
复数 complex(x) x.__complex__()
整数 int(x) x.__int__()
浮点数 float(x) x.__float__()
四舍五入到最近的整数 round(x) x.__round__()
四舍五入到最近的n位数 round(x, n) x.__round__(n)
最小整数 math.ceil(x) x.__ceil__()
最大整数 math.floor(x) x.__floor__()
截断x到0的最接近的整数 math.trunc(x) x.__trunc__()
数字作为列表索引 a_list[x] a_list[x.__index__()]

比较

如果你想... 所以,你写... Python调用...
等于 x == y x.__eq__(y)
不等于 x != y x.__ne__(y)
小于 x < y x.__lt__(y)
小于等于 x <= y x.__le__(y)
大于 x > y x.__gt__(y)
大于等于 x >= y x.__ge__(y)
布尔 if x: x.__bool__()

序列化

如果你想... 所以,你写... Python调用...
对象副本 copy.copy(x) x.__copy__()
深拷贝 copy.deepcopy(x) x.__deepcopy__()
序列化一个对象 pickle.dump(x, file) x.__getstate__()
序列化一个对象 pickle.dump(x, file) x.__reduce__()
序列化一个对象 pickle.dump(x, file, protocol_version) x.__reduce_ex__(protocol_version)
取出恢复后的状态 x = pickle.load(fp) x.__getnewargs__()
取出恢复后的状态 x = pickle.load(fp) x.__setstate__()

with 语句

with块限定了运行时上下文;在执行with语句时,"进入"上下文,并在执行块中的最后一个语句后"退出"上下文.

如果你想... 所以,你写... Python调用...
进入with语句块 with x: x.__enter__()
退出with语句块 with x: x.__exit__(exc_type, exc_value, traceback)

真正深奥的东西

如果你想... 所以,你写... Python调用...
一个类的构造函数 x = MyClass() x.__new__()
一个类的析构函数 del x x.__del__()
只有一组特定的属性需要定义 `` x.__solts__()
hash码 hash(x) x.__hash__()
获得一个属性的值 x.color type(x).__dict__['color'].__get__(x, type(x))
设置一个属性的值 x.color = 'PapayaWhip' type(x).__dict__['color'].__set__(x, 'PapayaWhip')
删除一个属性 del x.color type(x).__dict__['color'].__del__(x)
一个对象是否是你的一个类的实例 isinstance(x, MyClass) MyClass.__instancecheck__(x)
一个类是否是你的类的子类 isinstance(C, MyClass) MyClass.__subclasscheck__(C)
一个类是否是抽象基类的实例 isinstance(C, MyABC) MyABC.__subclasshook__(C)

Python正确调用__del__()特殊方法时非常复杂.为了完全理解它,你需要知道Python如何跟踪内存中的对象.这里有一篇关于Python垃圾收集和类析构函数的好文章.你还应该阅读关于弱引用,weakref模块,以及可能的gc模块以获得更好的度量.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容