零基础入门学习Python(23):魔法方法(3)属性访问
在讲解今天的内容之前,我们先重写两个函数__str__()和__repr__()
,第一个函数表示可以使用print()打印对象的值,第二个函数表示直接写出对象名就可以打印出对象的值。
>>> class Test:
def __str__(self):
return "Hello everyone."
>>> t1 = Test()
>>> t1 #直接写出t1得到它在内存中的位置
<__main__.Test object at 0x028859F0>
>>> print(t1) #需要调用print()才能打印出对象的值
Hello everyone.
>>> class Test:
def __repr__(self):
return "Hello everyone"
>>> t2 = Test() #重写__repr__()之后写出t2,则可以直接得到对象的值
>>> t2
Hello everyone
下面介绍一下Python属性访问的魔法方法:
1)__getattr__(self,name)
:定义当用户试图获取一个不存在的属性时的行为;
2)__getattribute__(self,name)
:定义当该类的属性被访问时的行为;
3)__setattr__(self,name,value)
:定义当一个属性被设置时的行为;
4)__delattr__(self,name)
:定义当一个属性被删除时的行为;
在访问属性的方法调用的时候,会先调用__getattribute__(self,name)
方法,当属性不存在时再调用__getattr__(self,name)
方法,下面通过举例验证一下。
>>> class TestAttr:
def __getattribute__(self,name): #分别重写属性访问的魔法方法
print('getattribute...')
return super().__getattribute__(name) #返回值调用没重写时候的方法
def __getattr__(self,name):
print('getattr...')
def __setattr__(self,name,value):
print('setattr...')
super().__setattr__(name,value)
def __delattr__(self, name):
print('delattr...')
super().__delattr__(name)
>>> a1 = TestAttr()
>>> a1.x #x属性不存在,则先调用__getattribute__()方法,再调用__getattr__()方法
getattribute...
getattr...
>>> a1.x = 2 #设置对象的x属性
setattr...
>>> a1.x #再次访问x时,则直接调用__getattribute__()方法并显示出x的值
getattribute...
2
>>> del a1.x #删除对象的x属性
delattr...
最后举一个例子:写一个矩形类,要求长宽默认为0,如果为一个叫square的属性赋值,说明是一个正方形,则长宽都等于square,最后计算矩形的面积。
>>> class Rectangle:
def __init__(self, length = 0, width = 0):
self.length = length #赋值操作,会进到__setattr__()方法中
self.width = width
def __setattr__(self, name, value): #重写__setattr__()方法
if name == "square": #先判断是否为正方形
self.length = value
self.width = value
else: #如果不是,则调用未重写时候设置属性的方法
super().__setattr__(name, value)
def getArea(self):
return self.length * self.width
>>> r1 = Rectangle(2,3) #初始化长宽
>>> r1.getArea()
6
>>> r1.length = 5 #可以只改变长或宽的值
>>> r1.getArea()
15
>>> r1.square = 7 #给square赋值时,长宽相等
>>> r1.length
7
>>> r1.width
7
>>> r1.getArea()
49
>>> r1.__dict__ #显示对象r1的属性
{'width': 7, 'length': 7}
由于对象的属性组成了一个字典类型的对象,所以设置属性时,除了可以使用super()方法之外,还可以利用字典的键值对给属性赋值,即super().__setattr__(name, value)
这行代码可以改为self.__dict__[name] = value
。当然,推荐大家使用super()方法。