zoukankan      html  css  js  c++  java
  • 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
    2
    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__
  • 相关阅读:
    saltstack高效运维
    python与RPC服务
    01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
    01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态
    01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
    01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务
    01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
    01-05-01-1【Nhibernate (版本3.3.1.4000) 出入江湖】延迟加载及其class和集合(set、bag等)的Lazy属性配置组合对Get和Load方法的影响
    01-01-01【Nhibernate (版本3.3.1.4000) 出入江湖】配置文件
    【log4net】配置文件
  • 原文地址:https://www.cnblogs.com/itwhite/p/12336110.html
Copyright © 2011-2022 走看看