特殊方法的名字以两个下划线开头,以两个下划线结尾(例如__getitem__
)。
比如obj[key]
的背后就是__getitem__
方法,为了能求得my_collection[key]
的值,解释器实际上会调用my_collection.__getitem__(key)
。
魔术方法(magic method)是特殊方法的昵称。
__new__()
是一个静态方法 (因为是特例所以你不需要显式地声明),它会将所请求实例所属的类作为第一个参数。其余的参数会被传递给对象构造器表达式 (对类的调用)。__new__()
的返回值应为新对象实例 (通常是 cls 的实例)。
__new__()
的目的主要是允许不可变类型的子类 (例如 int, str 或 tuple) 定制实例创建过程。它也常会在自定义元类中被重载以便定制类创建过程。
class Foo:
def __init__(self):
print("----init方法-----")
def __new__(cls):
eturn object.__new__(cls)
f = Foo() # ----init方法-----
print(f) # <__main__.Foo object at 0x00000225ACB0AF70>
如果__new__()
未返回一个 cls 的实例,则新实例的 __init__()
方法就不会被执行,并返回None
。
class Foo:
def __init__(self):
print("----init方法-----")
def __new__(cls):
pass
f = Foo()
print(f) # None
在实例 (通过 __new__()
) 被创建之后,返回调用者之前调用。其参数与传递给类构造器表达式的参数相同。一个基类如果有 __init__()
方法,则其所派生的类如果也有 __init__()
方法,就必须显式地调用它以确保实例基类部分的正确初始化;例如: super().__init__([args...])
因为对象是由__new__()
和 __init__()
协作构造完成的 (由__new__()
创建,并由 __init__()
定制),所以__init__()
返回的值只能是 None,否则会在运行时引发 TypeError。
class Foo:
def __init__(self):
return "hello world" # TypeError: __init__() should return None, not 'str'
def __new__(cls):
return object.__new__(cls)
f = Foo()
print(f)
在实例将被销毁时调用,又称析构器。 如果一个基类具有__del__()
方法,则其所派生的类如果也有__del__()
方法,就必须显式地调用它以确保实例基类部分的正确清除。
__del__()
方法可以 (但不推荐!) 通过创建一个该实例的新引用来推迟其销毁。这被称为对象 重生。
__del__()
是否会在重生的对象将被销毁时再次被调用是由具体实现决定的 ;当前的 CPython 实现只会调用一次。
由 repr()
内置函数调用以输出一个对象的“官方”字符串表示。通常情况下,直接输出某个实例化对象,得到的是“类名+object at+内存地址”。
返回值必须是一个字符串对象。如果一个类定义了__repr__()
但未定义__str__()
,则在需要该类的实例的“非正式”字符串表示时也会使用 __repr__()
。
此方法通常被用于调试,因此确保其表示的内容包含丰富信息且无歧义是很重要的。
class Foo:
def __init__(self):
self.name = 'nightwatchmans'
f = Foo()
print(f) # <__main__.Foo object at 0x00000221FFE9EC10>
重写类的__repr__()
方法,可以自定义输出实例化对象时的信息。
class Foo:
def __init__(self):
self.name = 'nightwatchmans'
def __repr__(self):
return f"{self.__class__.__name__} create by {self.name}"
f = Foo()
print(f) # Foo create by nightwatchmans
print(type(f)) # ,注意仅输出实例化对象时是字符串,对象的类型并未改变
由此可见,__repr__()
方法是类的实例化对象用来做“自我介绍”的方法。
通过str(object)
以及内置函数 format()
和 print()
调用以生成一个对象的“非正式”或格式良好的字符串表示。返回值必须为一个 字符串 对象。内置类型 object 所定义的默认实现会调用 object.__repr__()
。
__repr__
和__str__
的区别在于,后者是在str() 函数被使用,或是在用print 函数打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好,而 __repr__()
主要用于调试和开发。
如果你只想实现这两个特殊方法中的一个,__repr__
是更好的选择,因为如果一个对象没有__str__
函数,而Python 又需要调用它的时候,解释器会用__repr__
作为替代。
通过 bytes 调用以生成一个对象的字节串表示。这应该返回一个 bytes 对象。
通过 format() 内置函数、扩展、格式化字符串字面值 的求值以及 str.format() 方法调用以生成一个对象的“格式化”字符串表示。 format_spec 参数为包含所需格式选项描述的字符串。 format_spec 参数的解读是由实现 format() 的类型决定的,不过大多数类或是将格式化委托给某个内置类型,或是使用相似的格式化选项语法。
返回值必须为一个字符串对象。
[n]
来访问序列中的值,另外,因为 __getitem__
方法把[]
操作交给了 self._cards
列表,所以自动支持切片操作。for i in obj
迭代。当调用 for i in obj
时,其实用的是 iter(obj)
,调用的 __iter__
方法。但是如过没有实现 __iter__
方法,那么它会令 position
从 0
开始递增,直到触发 IndexError
结束,且只能是 IndexError
类型的 Error
,否则触发错误后会引发异常。__contains__
,它会按顺序做一次迭代搜索)__len__
)默认情况下,我们自己定义的类的实例总被认为是真的,除非这个类对__bool__
或者__len__
函数有自己的实现。bool(x)
的背后是调用x.__bool__()
的结果;如果不存在__bool__
方法,那么bool(x)
会尝试调用x.__len__()
。若返回0,则bool 会返回False;否则返回True。