本文主要是介绍接上哈哈哈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
2,当对象即将被销毁时,会调用__del__(self)魔法方法
>>> class C:
... def __init__(self):
... print("我来了")
... def __del__(self):
... print("我走了")
...
>>> c=C()
我来了
>>> del c
我走了
>>> c=C()
我来了
>>> b=c
>>> del c
>>> del b
我走了
只有当对象的引用被删除时才会调用__del__(self)魔法方法,例如上码中将c赋值给b,删除小c时没有触发魔法方法,放b也被删除时,才触发魔法方法。
3,利用重写__del__(self)来实现对象的重生
本质:通过创建一个该实例对象的新引用来推迟其销毁。
(1)通过全局变量
>>> class D:
... def __init__(self,name):
... self.name = name
... def __del__(self):
... global x
... x=self
...
>>> d=D("小甲鱼")
>>> d
<__main__.D object at 0x000001374BC2B8B0>
>>> del d
>>> x
<__main__.D object at 0x000001374BC2B8B0>
>>> x.name
'小甲鱼'
(2)通过闭包
>>> class E:
... def __init__(self,name,func):
... self.name = name
... self.func = func
... def __del__(self):
... self.func(self)
...
>>> def outter():
... x = 0
... def inner(y=None):
... nonlocal x
... if y:
... x = y
... else:
... return x
... return inner
...
>>> f = outter()
>>> e = E("小甲鱼",f)
>>> e
<__main__.E object at 0x000001374BDC5310>
>>> e.name
'小甲鱼'
>>> del e
>>> g = f()
>>> g
<__main__.E object at 0x000001374BDC5310>
>>> g.name
'小甲鱼'
通过闭包将self保存在外部函数的变量x中,内部函数的作用是窃取self对象。
P67,P68 运算相关的魔法方法
1,运算相关的魔法方法
2,对__add__(self,other)魔法方法重写
>>> class S(str):
... def __add__(self,other):
... return len(self) + len(other)
...
>>> s1 = S("FishC")
>>> s2 = S("Python")
>>> s1 + s2
11
>>> s1 + "Python"
11
>>> "FishC" + s2
'FishCPython'
#从 s1 + "Python" 和 "FishC" + s2 的结果来看,触发的魔法方法是加号前的一项的
3,__radd__() 方法
4,__iadd__()方法,实现运算加赋值
>>> class S(str):
... def __iadd__(self,other):
... return len(self) + len(other)
...
>>> s1 = S("Apple")
>>> s2 = "Banana"
>>> s1 += s2
>>> s1
11
>>> type(s1)
<class 'int'>
5,对__int__()魔法方法进行重写
实现中文大写数字转化为 int 类型。
6,
按位与:&
按位或:|
按位异或:^
按位取反:~,(涉及到补码)
7,__index__()魔法方法
对象被当作索引值时触发
>>> class C:
... def __index__(self):
... print("被拦截了")
... return 3
...
>>> c = C()
>>> s = "FishC"
>>> s[c]
被拦截了
'h'
P69 属性访问相关的魔法方法
1,
hasattr()方法,判断对象中是否有某属性
getattr()方法,得到对象中某属性的值,(与:“对象 . 属性” 等价)
setattr()方法,设置对象中某属性的值,(与:“对象 . 属性 = other” 等价)
delattr()方法,删除对象中某属性
>>> class C:
... def __init__(self,name,age):
... self.name = name
... self.__age = age
...
>>> c = C("小甲鱼",18)
>>> hasattr(c,"name")
True
>>> getattr(c,"name")
'小甲鱼'
>>> setattr(c,"name","老乌龟")
>>> getattr(c,"name")
'老乌龟'
>>> delattr(c,"name")
>>> hasattr(c,"name")
False
2,
getattr()方法对应的魔法方法是__getattribute__(),而不是__getattr__(),__getattr__()也是一个魔法方法,但未与getattr()对应
>>> class C:
... def __init__(self,name,age):
... self.name = name
... self.__age = age
... def __getattribute__(self,attrname):
... print("拦截到了getattribute")
... return super().__getattribute__(attrname)
...
>>> c=C("小甲鱼",18)
>>> getattr(c,"name")
拦截到了getattribute
'小甲鱼'
>>> c.name #与getattr(c,"name")等效
拦截到了getattribute
'小甲鱼'
这是super()调用的是父类object的__getattribute__方法,Python中所有类默认继承object,调用的object中的__getattribute__(attrname)方法的结果就是return attrname
3,__getattr__()魔法方法,不与getattr()对应,触发条件是,获取不存在的属性时触发
>>> class C:
... def __init__(self,name,age):
... self.name = name
... self.__age = age
... def __getattribute__(self,attrname):
... print("拦截到了getattribute")
... return super().__getattribute__(attrname)
... def __getattr__(self,attrname):
... print("拦截到了getattr")
...
>>> c = C("小甲鱼",18)
>>> c.name
拦截到了getattribute
'小甲鱼'
>>> c.na
拦截到了getattribute
拦截到了getattr
4,__setattr__()魔法方法
触发条件:当捕捉到对象出现赋值操作时。
容易出现无限递归
>>> class D:
... def __setattr__(self,name,value):
... self.name = value #此句话也会触发__setattr__()魔法方法,
... #形成无限递归
>>> d = D()
>>> d.name = "小甲鱼"
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 3, in __setattr__File "<stdin>", line 3, in __setattr__File "<stdin>", line 3, in __setattr__[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
解决方法
>>> class D:
... def __setattr__(self,name,value):
... self.__dict__[name] = value
...
>>> d = D()
>>> d.name = "小甲鱼"
>>> d.name
'小甲鱼'
5,__delattr__()魔法方法
__delattr__()魔法方法也要防止无限递归,
>>> class E:
... def __delattr__(self,name):
... del self.__dict__[name]
...
>>> e = E()
>>> e.name = "小甲鱼"
>>> e.__dict__
{'name': '小甲鱼'}
>>> del e.name
>>> e.__dict__
{}
P70
1,__getitem__() 和 __setitem__() 魔法方法
__getitem__()触发条件:对象被索引,被切片,被迭代
__setitem__()触发条件:对象被索引赋值,切片赋值
>>> class D:
... def __init__(self,data):
... self.data = data
... def __getitem__(self,index):
... print("hello~,getitem")
... return self.data[index]
... def __setitem__(self,index,value):
... self.data[index] = value
... print("hello~,setitem")
...
>>> d=D([11,2,3,4,5,6])
>>> d
<__main__.D object at 0x000001374BE8C730>
>>> d.data
[11, 2, 3, 4, 5, 6]
>>> d[0]
hello~,getitem
11
>>> d[1:3]
hello~,getitem
[2, 3]
>>> d[0]=111
hello~,setitem
1,__iter__(self) 和 __next__(self) 魔法方法
略
P71
1,__contains__魔法方法,对应 in,not in
该魔法方法的代偿现象:略
2,__bool__魔法方法,对应 bool
该魔法方法的代偿现象:略
3,比较运算符的魔法方法:略
P72
1,__call__(self[,args,...])魔法方法
2,__str__(self)和__repr__(self)魔法方法
3, eval(str)函数:将str去引号后执行
P73
property()
1,
property
是 Python 中的一个内置装饰器,它允许您将一个方法转换为属性,从而可以以属性的方式访问和修改对象的值。使用 property
装饰器可以实现属性的读取、写入和删除操作的自定义逻辑。
property
装饰器通常与三个方法一起使用,这些方法定义了属性的行为:
(1)getter
方法:负责获取属性的值,通常命名为 get_xxx
,其中 xxx
是属性的名称。
(2)setter
方法:负责设置属性的值,通常命名为 set_xxx
,其中 xxx
是属性的名称。
(3)deleter
方法:负责删除属性的值,通常命名为 del_xxx
,其中 xxx
是属性的名称。
以下是一个使用 property
装饰器的示例:
class D:def __init__(self, x):self._x= xdef get_x(self):return self._xdef set_x(self, value):if value < 0:raise ValueError("x cannot be negative")self._x = valuedef del_x(self):print("Deleting the x")del self._xx= property(get_x, set_x, del_x)
# 创建 D 对象
d= D(5)
# 读取属性
print(d.x) # 输出: 5
# 设置属性
d.x= 10
print(d.x) # 输出: 10
# 删除属性
del d.x # 输出: Deleting the x
在上述示例中,D
类使用 property
装饰器定义了 x
属性的 getter、setter 和 deleter 方法。这使得 x
属性可以像普通属性一样被读取、设置和删除。
2,
用魔法方法实现上述功能
>>> class D:
... def __init__(self, x):
... self._x = x
... def __getattribute__(self, name):
... if name == "x":
... return object.__getattribute__(self, "_x")
... return super().__getattribute__(name)
... def __setattr__(self, name, value):
... if name == "x":
... if value < 0:
... raise ValueError("x cannot be negative")
... object.__setattr__(self, "_x", value)
... else:
... super().__setattr__(name, value)
... def __delattr__(self, name):
... if name == "x":
... print("Deleting the x")
... object.__delattr__(self, "_x")
... else:
... super().__delattr__(name)
...
>>> # 创建 D 对象
>>> d = D(5)
>>>
>>> # 读取属性
>>> print(d.x) # 输出: 5
5
>>>
>>> # 设置属性
>>> d.x = 10
>>> print(d.x) # 输出: 10
10
>>> # 删除属性
>>> del d.x # 输出: Deleting the x
Deleting the x
3,property创建一个只读的对象
>>> class E:
... def __init__(self):
... self._x = 520
... @property
... def x(self):
... return self._x
...
>>> e = E()
>>> e.x
520
>>> e.x = 250
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
换成非语法糖就是:
>>> class E:
... def __init__(self):
... self._x = 520
... def x(self):
... return self._x
... x = property(x)
...
>>> e = E()
>>> e.x
520
>>> e.x = 250
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
为什么是只读呢:
property有三个参数,分别是获取,写入和删除,此处只传入了第一个参数,只能获取,不支持写入和删除。
用语法糖形式的情况下,传入三个参数
>>> class E:
... def __init__(self):
... self._x = 520
... @property
... def x(self):
... return self._x
... @x.setter
... def x(self,value):
... self._x = value
... @x.deleter
... def x(self):
... del self._x
...
>>> e = E()
>>> e.x
520
>>> e.x = 250
>>> e.x
250
>>> e.__dict__
{'_x': 250}
>>> del e.x
>>> e.__dict__
{}
这篇关于接上哈哈哈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!