Python 杂记:特殊方法(Special Methods)
特殊方法简介
方法 | 描述 |
---|---|
__init__() | 构造函数 |
__len__() | 重载len(),例如:len(obj) |
__getitem__() | 重载[](读操作),例如:obj[0] |
__setitem__() | 重载[](写操作),例如:obj[0] = 123 |
__str__() | 重载 str(),例如:str(obj) |
__repr__() | 重载 repr(),例如:repr(obj),遇到字符串格式化 %r 时会调用它 |
__abs__() | 重载 abs(),例如:abs(obj) |
__bool__() | 重载 bool(),例如:bool(obj) |
__add__() | 重载加法操作符+,例如:obj1 + obj2 |
__mul__() | 重载乘法操作符*,例如:obj1 * 123 |
... | ... |
更多的特殊方法请参考本文末尾“特殊方法列表”。
官方文档关于这些特殊方法的解释请参考:https://docs.python.org/3/reference/datamodel.html#special-method-names。
特殊方法示例
__init__()
class Foo:
def __init__(self):
print("Foo::__init__() is called")
foo = Foo() # Foo::__init__() is called
__len__()、__getitem__()、__setitem__()
class Foo:
def __init__(self):
self.data = []
def __len__(self):
print("Foo::__len__() is called")
return len(self.data)
def __getitem__(self, index):
print("Foo::__getitem__(%d) is called" % index)
return self.data[index]
def __setitem__(self, index, value):
print("Foo::__setitem__(%d,%r) is called" % (index, value))
if len(self.data) > index:
self.data[index] = value
else:
self.data.append(value)
foo = Foo()
foo[0] = 123 # Foo::__setitem__(0,123) is called
foo[1] = "abcd" # Foo::__setitem__(1,'abcd') is called
print(len(foo)) # Foo::__len__() is called\n2
foo[0] # Foo::__getitem__(0) is called
__str__()、__repr__()
__str__() 与 __repr__() 类似,都是将对象转换为字符串,区别:
- __str__() 倾向于返回可读性更高的字符串(readable, pretty print);
- __repr__() 倾向于返回准确、无歧义的字符串(unambiguous),例如:"%r, %r" % (123, "123") 结果是"123, '123'",同样都是123,前者是数字,后者是字符串,必须准确表达;
- 当 __str__() 没有被定义但是定义了 __repr__() 时,__repr__() 会被 str() 借用,反过来则不会。
示例:
class A:
pass
a = A() # 当 __repr__() 和 __str__() 都没有定义,使用默认输出
print(str(a)) # <__main__.A instance at 0x00000000024E4A88>
print(repr(a)) # <__main__.A instance at 0x00000000024E4A88>
print("%r" % a) # <__main__.A instance at 0x00000000024E4A88>
class B:
def __repr__(self):
return "B::__repr__"
b = B() # 当定义了 __repr__() 但没有定义 __str__()
print(str(b)) # B::__repr__ # str() 会调用 __repr__()
print(repr(b)) # B::__repr__
print("%r" % b) # B::__repr__
class C:
def __str__(self):
return "C::__str__"
c = C() # 当定义了 __str__() 但没有定义 __repr__(),repr()不会调用 __str__()
print(str(c)) # C::__str__
print(repr(c)) # <__main__.C instance at 0x00000000024E4B48>
print("%r" % c) # <__main__.C instance at 0x00000000024E4B48>
class D:
def __repr__(self):
return "D::__repr__"
def __str__(self):
return "D::__str__"
d = D() # # 当 __repr__() 和 __str__() 都有定义,各自使用各自的
print(str(d)) # D::__str__
print(repr(d)) # D::__repr__
print("%r" % d) # D::__repr__
参考: https://stackoverflow.com/questions/1436703/difference-between-str-and-repr/1436756#1436756
特殊方法列表
注:本小节中表格数据来自于《流畅的Python》。
官方文档关于这些特殊方法的解释请参考:https://docs.python.org/3/reference/datamodel.html#special-method-names。
跟运算符无关的特殊方法
类别 | 方法名 |
---|---|
字符串 / 字节序列表示形式 | __repr__、__str__、__format__、__bytes__ |
数值转换 | __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__ |
集合模拟 | __len__、__getitem__、__setitem__、__delitem__、__contains__ |
迭代枚举 | __iter__、__reversed__、__next__ |
可调用模拟 | __call__ |
上下文管理 | __enter__、__exit__ |
实例创建和销毁 | __new__、__init__、__del__ |
属性管理 | __getattr__、__getattribute__、__setattr__、__delattr__、__dir__ |
属性描述符 | __get__、__set__、__delete__ |
跟类相关的服务 | __prepare__、__instancecheck__、__subclasscheck__ |
跟运算符相关的特殊方法
类别 | 方法名和对应的运算符 |
---|---|
一元运算符 | __neg__ -、__pos__ +、__abs__ abs() |
比较运算符 | __lt__ <、__le__ <=、__eq__ ==、__ne__ !=、__gt__ >、__ge__ >= |
比较运算符 | __lt__ <、__le__ <=、__eq__ ==、__ne__ !=、__gt__ >、__ge__ >= |
算术运算符 | __add__ +、__sub__ -、__mul__ *、__truediv__ /、__floordiv__ //、__mod__ %、__divmod__ divmod()、__pow__ ** 或pow()、__round__ round() |
反向算术运算符 | __radd__、__rsub__、__rmul__、__rtruediv__、__rfloordiv__、__rmod__、__rdivmod__、__rpow__ |
增量赋值算术运算符 | __iadd__、__isub__、__imul__、__itruediv__、__ifloordiv__、__imod__、__ipow__ |
位运算符 | __invert__ ~、__lshift__ <<、__rshift__ >>、__and__ &、__or__ |、__xor__ ^ |
反向位运算符 | __rlshift__、__rrshift__、__rand__、__rxor__、__ror__ |
增量赋值位运算符 | __ilshift__、__irshift__、__iand__、__ixor__、__ior__ |