接上哈哈哈

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,运算相关的魔法方法

接上哈哈哈_第1张图片

接上哈哈哈_第2张图片

接上哈哈哈_第3张图片

接上哈哈哈_第4张图片

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__() 方法

接上哈哈哈_第5张图片

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)

5,对__int__()魔法方法进行重写

接上哈哈哈_第6张图片

实现中文大写数字转化为 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 "", line 1, in 
  File "", line 3, in __setattr__
  File "", line 3, in __setattr__
  File "", 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= x
    def get_x(self):
        return self._x
    def set_x(self, value):
        if value < 0:
            raise ValueError("x cannot be negative")
        self._x = value
    def del_x(self):
        print("Deleting the x")
        del self._x
    x= 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 "", line 1, in 
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 "", line 1, in 
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__
{}

你可能感兴趣的:(python,linux,开发语言)