特殊方法
特殊方法的名字以两个下划线开头,以两个下划线结尾(例如__getitem__)。
比如obj[key]的背后就是__getitem__方法,为了能求得my_collection[key]的值,解释器实际上会调用my_collection.__getitem__(key)。
魔术方法(magic method)是特殊方法的昵称。
基本特殊方法
__new__()
__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
__init__()
在实例 (通过 __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__()方法可以 (但不推荐!) 通过创建一个该实例的新引用来推迟其销毁。这被称为对象 重生。
__del__()是否会在重生的对象将被销毁时再次被调用是由具体实现决定的 ;当前的 CPython 实现只会调用一次。
__repr__()
由 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)) # <class '__main__.Foo'> ,注意仅输出实例化对象时是字符串,对象的类型并未改变
由此可见,__repr__()方法是类的实例化对象用来做“自我介绍”的方法。
__str__()
通过str(object)以及内置函数 format()和 print()调用以生成一个对象的“非正式”或格式良好的字符串表示。返回值必须为一个 字符串 对象。内置类型 object 所定义的默认实现会调用 object.__repr__()。
__repr__和__str__的区别在于,后者是在str() 函数被使用,或是在用print 函数打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好,而 __repr__()主要用于调试和开发。
如果你只想实现这两个特殊方法中的一个,__repr__是更好的选择,因为如果一个对象没有__str__函数,而Python 又需要调用它的时候,解释器会用__repr__作为替代。
__bytes__()
通过 bytes 调用以生成一个对象的字节串表示。这应该返回一个 bytes 对象。
__format__()
通过 format() 内置函数、扩展、格式化字符串字面值 的求值以及 str.format() 方法调用以生成一个对象的“格式化”字符串表示。 format_spec 参数为包含所需格式选项描述的字符串。 format_spec 参数的解读是由实现 format() 的类型决定的,不过大多数类或是将格式化委托给某个内置类型,或是使用相似的格式化选项语法。
返回值必须为一个字符串对象。
__getitem__
- 可以使用位置索引
[n]来访问序列中的值,另外,因为__getitem__方法把[]操作交给了self._cards列表,所以自动支持切片操作。 - 对象可迭代,如可以用
for i in obj迭代。当调用for i in obj时,其实用的是iter(obj),调用的__iter__方法。但是如过没有实现__iter__方法,那么它会令position从0开始递增,直到触发IndexError结束,且只能是IndexError类型的Error,否则触发错误后会引发异常。 - 可以用in运算符(即使没实现
__contains__,它会按顺序做一次迭代搜索) - 可以用random.choice()方法来随机获取一个元素(用这个方法还需要额外实现
__len__)
__bool__()
默认情况下,我们自己定义的类的实例总被认为是真的,除非这个类对__bool__或者__len__函数有自己的实现。bool(x)的背后是调用x.__bool__()的结果;如果不存在__bool__方法,那么bool(x)会尝试调用x.__len__()。若返回0,则bool 会返回False;否则返回True。
498

被折叠的 条评论
为什么被折叠?



