这是一篇很不错的总结文章,简单易理解,洒家忍不住要转载收藏一下。
源文链接:http://algo.site/?cat=60
基础:
| 如果你想… | 所以,你写… | 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 / 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 /= 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` |
还有一些"单个数"数学运算可以让你自己对类似数字的对象进行数学运算.
| 如果你想… | 所以,你写… | 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 模块以获得更好的度量.