Python 特殊方法

特殊方法

特殊方法的名字以两个下划线开头,以两个下划线结尾(例如__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__方法,那么它会令 position0开始递增,直到触发 IndexError结束,且只能是 IndexError类型的 Error,否则触发错误后会引发异常。
  • 可以用in运算符(即使没实现 __contains__,它会按顺序做一次迭代搜索)
  • 可以用random.choice()方法来随机获取一个元素(用这个方法还需要额外实现 __len__

__bool__()

默认情况下,我们自己定义的类的实例总被认为是真的,除非这个类对__bool__或者__len__函数有自己的实现。bool(x)的背后是调用x.__bool__()的结果;如果不存在__bool__方法,那么bool(x)会尝试调用x.__len__()。若返回0,则bool 会返回False;否则返回True。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值