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__

猜你喜欢

转载自www.cnblogs.com/itwhite/p/12336110.html