17.python-魔术方法

发布时间 2023-07-05 19:23:05作者: 贝壳里的星海

python 魔术方法-示例

特殊属性

属性 含义
__name__ 类、函数、方法的名字,不能实例调用
__module__ 类、函数、方法所在的模块
__class__ 对象、属性的类
__bases__ 类的基类,不能实例调用
__doc__ 类、函数的文档
__dict__ 类或者实例的属性
class People(object):
    # 实例化对象
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("__init__")

p1 = People("beike", 18)
print(People.__name__)
print(People.__class__)
print(People.__bases__)
print(People.__doc__)
print(People.__dict__)
#
print("-"*50)
print(p1.__class__)
print(p1.__doc__)
print(p1.__dict__)

# 执行结果----------------------------------------------------------------------------
__init__
People
<class 'type'>
(<class 'object'>,)
None
{'__module__': '__main__', '__init__': <function People.__init__ at 0x0000017602883820>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
--------------------------------------------------
<class '__main__.People'>
None
{'name': 'beike', 'age': 18}

构造方法

魔法方法 含义
__new__(cls[, ...]) __new__ 是在一个对象实例化的时候所调用的第一个方法
__init__(self[, ...]) 构造器,当一个实例被创建的时候调用的初始化方法
__del__(self) 析构器,当一个实例被销毁的时候调用的方法
__call__(self[, args...]) 允许一个类的实例像函数一样被调用:x(a, b) 调用 x.__call__(a, b)
构造方法__new__
触发时机: 实例化对象时自动触发(在__init__之前触发)
参数:至少一个cls 接收当前类,其他参数根据初始化方法参数决定
返回值:必须返回一个对象实例,没有返回值,则实例化对象的结果为 None,新实例的 __init__() 方法就不会被执行
作用:实例化对象

初始化方法__init__
触发机制:实例化对象之后立即触发
参数:至少有一个self,接收当前对象,其他参数根据需要进行定义
返回值:无
作用:初始化对象的成员

析构方法__del__
触发时机:当该类对象被销毁时,自动触发
参数:一个self,接受当前对象
返回值:无
作用:关闭或释放对象创建时资源
注意:del不一定会触发当前方法,只有当前对象没有任何变量引用时才会触发

可调用对象__call__    
调用对象的魔术方法
触发时机:将对象当作函数调用时触发,  方式: 对象()
参数:至少一个self接收对象,其余根据调用时参数决定
返回值:自定义
作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
class People(object):
    # 创建对象
    def __new__(cls, *args, **kwargs):
        print("触发了构造方法")
        ret = super().__new__(cls) # 调用父类的__new__()方法创建对象
        return ret ## 将对象返
    # 实例化对象
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("初始化方法")
    #  删除对象
    #   del 对象名或者程序执行结束之后
    def __del__(self):
        print("析构方法,删除对象")


if __name__ == '__main__':
    p1 = People('xiaoming', 16)
	del p1
    print("程序结束")
    
触发了构造方法
初始化方法
析构方法,删除对象
程序结束

基本方法

魔法方法 含义
__len__(self) 定义当被 len() 调用时的行为
__str__(self) 定义当被 str() 调用时的行为
__repr__(self) 定义当被 repr() 调用时的行为
__format__(self, format_spec) 定义当被 format() 调用时的行为
__bool__(self) 判断对象的bool()值时执行的方法,返回值只能是bool类型, 应该返回 True 或 False
__bytes__(self) 定义当被 bytes() 调用时的行为
__hash__(self) 定义当被 hash() 调用时的行为
__len__
触发时机:使用len(对象) 的时候触发
参数:一个参数self
返回值:必须是一个整型
作用:可以设置为检测对象成员个数,但是也可以进行其他任意操作
注意:返回值必须必须是整数,否则语法报错,另外该要求是格式要求

__bool__
触发时机: 使用bool(对象)的时候触发
参数:一个self接收对象
返回值:必须是布尔值
作用:根据实际情况决定,可以作为快捷方式使用
注意:仅适合于返回布尔值的操作

__repr__
触发时机:在使用repr(object)的时候触发
参数:一个self接收对象
返回值:必须是字符串
作用:将对象转使用repr化为字符串时使用,也可以用于快捷操作
此方法通常被用于调试

__str__
触发时机: 通过 str(object) 以及内置函数 format() 和 print() 
参数:一个self接收对象
返回值:必须是字符串
作用:将对象转使用str化为字符串时使用,也可以用于快捷操作

__format__
触发时机:使用字符串.format(object)时候触发
参数:一个self接收对象,一个参数接收format的{}中的格式,例如:>5
返回值:必须是字符串
作用:设置对象可以作为format的参数,并且自定义对象格式化的规则
注意:无
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person(name='{self.name}', age={self.age})"

    def __str__(self):
        return f"{self.name}, {self.age}"

    def __format__(self, format_spec):
        if format_spec == "":
            return  "s"
        if format_spec == "s":
            return str(self)
        elif format_spec == "r":
            return repr(self)
        elif format_spec == "a":
            return f"Person('{self.name}', {self.age})"
        else:
            raise ValueError(f"Invalid format specifier '{format_spec}'")

person = Person("Alice", 30)
print(person)                 # 输出:Alice, 30
print(str(person))            # 输出:Alice, 30
print(repr(person))           # 输出:Person(name='Alice', age=30)
print("{}".format(person))    # 输出:s
print("{!s}".format(person))  # 输出:Alice, 30
print("{!r}".format(person))  # 输出:Person(name='Alice', age=30)
print("{!a}".format(person))  # 输出:Person('Alice', 30)

模拟容器类

容器类型
__len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self) 定义当迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
__len__
1 内建函数len(),返回对象的长度(>=0的整数)
  如果把对象当作容器类型看,就如同list或者dict
2 bool()函数调用的时候,如果没有__bool__()方法
  则会看__len__()方法是否存在,存在返回非0为真

__iter__
1 迭代容器时,调用,返回一个新的迭代器

__contains__
1 in成员运算符,没有实现,就调用__iter__方法遍历

__getitem__
1 实现self[key]访问。序列对象,key接受整数为索引,或为切片
2 对于set和dict,key为hashable。key不存在引发KeyError异常

__setitem__
1 和__getitem__的访问类似,是设置值的方法

__missing__
1 字典或其子类使用__getitem__()调用时,key不存在执行该方法

# 模拟购物车类
class Cart:
    def __init__(self):
        self.items = []
        
    def __len__(self):
        return len(self.items)
    
    def additem(self, item):
        self.items.append(item)
        
    def __iter__(self):
        return iter(self.items)
    
    def __getitem__(self, index):
        return self.items[index]
    
    def __setitem__(self, key, value):
        self.items[key] = value
        
    def __str__(self):
        return str(self.items)
    
    def __add__(self, other):
        self.items.append(other)
        return self

cart = Cart()
cart.additem(1)
cart.additem('a')
cart.additem('c')

print(cart)  			   # [1, 'a', 'c']
print(len(cart))  		   # 3
for x in cart:
    print(x, end = ' ')    # 1 a c 
print(3 in cart)  		   # False
print(1 in cart)           # True
print(cart[1])             # a
cart[1] = 'xyz'				
print(cart)                # [1, 'xyz', 'c']
print(cart + 4 + 'aaa' + 'ppp')   # [1, 'xyz', 'c', 4, 'aaa', 'ppp']
print(cart.__add__('iii'))        # [1, 'xyz', 'c', 4, 'aaa', 'ppp', 'iii']
print(cart.items)                 # [1, 'xyz', 'c', 4, 'aaa', 'ppp', 'iii']

属性相关

有关属性
__getattr__(self, name) 定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self, name) 定义当该类的属性被访问时的行为
__setattr__(self, name, value) 定义当一个属性被设置时的行为
__delattr__(self, name) 定义当一个属性被删除时的行为
__dir__(self) 定义当 dir() 被调用时的行为,返回对象的所有成员名称列表
__get__(self, instance, owner) 定义当描述符的值被取得时的行为
__set__(self, instance, value) 定义当描述符的值被改变时的行为
__delete__(self, instance) 定义当描述符的值被删除时的行为

__getattribute__() 方法与 __getattr__() 方法的行为不同。__getattribute__() 方法用于访问任何属性,而 __getattr__() 方法仅在对象没有指定属性时才会被调用。

__getattr__
触发时机:获取不存在的对象成员时触发
参数:一个是接收当前对象的self,一个是获取成员名称的字符串
返回值:必须有值
作用:为访问不存在的属性设置值

__setattr__
触发时机:设置对象成员值的时候触发
参数:1个当前对象的self,一个是要设置的成员名称字符串,一个是要设置的值
返回值:无 过程操作
作用:接管设置操作,可以在设置前之前进行判断验证等行为
注意:在当前方法中无法使用成员=值的方式直接设置成员,否则会无限递归,必须借助object的设置方法来完成


__dir__
触发时机: 会在对相应对象调用 dir() 时被调用
参数:1个当前对象的self
返回值: 必须是一个序列
作用:  dir() 会把返回的序列转换为列表并对其排序。
注意:在当前方法中无法使用成员=值的方式直接设置成员,否则会无限递归,必须借助object的设置方法来完成

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getattr__(self, name):
        if name == "email":
            return f"{self.name.lower()}@example.com"
        else:
            raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")

    def __setattr__(self, name, value):
        if name == "age":
            if value < 0:
                raise ValueError("Age cannot be negative")
        super().__setattr__(name, value)

    def __delattr__(self, name):
        if name == "email":
            raise AttributeError("Cannot delete email attribute")
        super().__delattr__(name)

person = Person("Alice", 30)
print(person.email)  # 输出:alice@example.com
person.age = 40
print(person.age)    # 输出:40
del person.email     # 引发 AttributeError 异常
class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def __getattribute__(self, name):
        if name == "name":
            return "Hello, " + object.__getattribute__(self, "_name")
        elif name == "age":
            return object.__getattribute__(self, "_age")
        else:
            return object.__getattribute__(self, name)

person = Person("Alice", 30)
print(person.name)  # 输出:Hello, Alice
print(person.age)   # 输出:30
print(person.xyz)   # 引发 AttributeError 异常

比较操作符

__lt__(self, other) 定义小于号的行为:x < y 调用 x.__lt__(y)
__le__(self, other) 定义小于等于号的行为:x <= y 调用 x.__le__(y)
__eq__(self, other) 定义等于号的行为:x == y 调用 x.__eq__(y)
__ne__(self, other) 定义不等号的行为:x != y 调用 x.__ne__(y)

运算符相关

算数运算符 运算符 说明
__add__(self, other) p1+p2 定义加法的行为:+
__sub__(self, other) p1-p2 定义减法的行为:-
__mul__(self, other) p1*p2 定义乘法的行为:*
__truediv__(self, other) p1/p2 定义真除法的行为:/
__floordiv__(self, other) p1//p2 定义整数除法的行为://
__mod__(self, other) p1%p2 定义取模算法的行为:%
__divmod__(self, other) (a // b, a % b) 定义当被 divmod() 调用时的行为
__pow__(self, other[, modulo]) p1**p2 定义当被 power() 调用或 ** 运算时的行为
__lshift__(self, other) p1<<p2 定义按位左移位的行为:<<
__rshift__(self, other) p1>>p2 定义按位右移位的行为:>>
__and__(self, other) p1&p2 定义按位与操作的行为:&
__xor__(self, other) p1^p2 定义按位异或操作的行为:^
__or__(self, other) p1|p2 定义按位或操作的行为:|

反运算

反运算法
__radd__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rsub__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rmul__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rtruediv__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rfloordiv__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rmod__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rdivmod__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rpow__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rlshift__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rrshift__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rand__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rxor__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__ror__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)

增量赋值运算

增量赋值运算 说明
__iadd__(self, other) 定义赋值加法的行为:+=
__isub__(self, other) 定义赋值减法的行为:-=
__imul__(self, other) 定义赋值乘法的行为:*=
__itruediv__(self, other) 定义赋值真除法的行为:/=
__ifloordiv__(self, other) 定义赋值整数除法的行为://=
__imod__(self, other) 定义赋值取模算法的行为:%=
__ipow__(self, other[, modulo]) 定义赋值幂运算的行为:**=
__ilshift__(self, other) 定义赋值按位左移位的行为:<<=
__irshift__(self, other) 定义赋值按位右移位的行为:>>=
__iand__(self, other) 定义赋值按位与操作的行为:&=
__ixor__(self, other) 定义赋值按位异或操作的行为:^=
__ior__(self, other) 定义赋值按位或操作的行为:|=

一元操作符

一元操作符
__pos__(self) 定义正号的行为:+x
__neg__(self) 定义负号的行为:-x
__abs__(self) 定义当被 abs() 调用时的行为
__invert__(self) 定义按位求反的行为:~x

类型转换

类型转换
__complex__(self) 定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self) 定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self) 定义当被 float() 调用时的行为(需要返回恰当的值)
__round__(self[, n]) 定义当被 round() 调用时的行为(需要返回恰当的值)
__index__(self) 1. 当对象是被应用在切片表达式中时,实现整形强制转换 2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index 3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值

上下文管理器

魔术方法 说明
__enter__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
__exit__(self, exc_type, exc_value, traceback) 定义获取容器中指定元素的行为,相当于 self[key]

上下文管理器 详细 见contextlib

参考资料

https://zhuanlan.zhihu.com/p/344951719

https://blog.csdn.net/weixin_44983653/article/details/123968967

https://blog.csdn.net/weixin_44983653/article/details/123968967