Python笔记(二十六)_魔法方法_属性的魔法方法

2023-04-20,,

属性的魔法方法

__getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法

__setattr__(self,name,value):当一个属性被设置时,自动触发

__delattr__(self,name):当一个属性被删除时,自动触发

>>>class C:
  def __getattribute__(self,name):
    print('getattribute')
  def __getattr__(self,name):
    print('getattr')
  def __setattr__(self,name,value):
    print('setattr')
  def __delattr__(self,name):
    print('delattr')
>>>c = C()
>>>c.x
getarrribute

此处没有调用并打印getattr的原因,要从实例对象属性的访问顺序说起:

首先调用getattribute -> 然后在实例对象中查找 -> 继续在实例的类中查找 -> 最后在父类中查找 -> 均无法找到时调用getattr方法

是要当所有流程都走完,都没找到该属性,才会调用getattr方法,但由于重写了getattribute方法,所以需要用super()函数来调用父类

>>>class C:
  def __getattribute__(self,name):
    print('getattribute')
    super().__getattribute__(name)
  def __getattr__(self,name):
    print('getattr')
  def __setattr__(self,name,value):
    print('setattr')
  def __delattr__(self,name):
    print('delattr')
>>>c = C()
>>>c.x
getarrribute
getattr
>>>c.x = 1
setattr
>>>c.x
getarrribute
1
>>>del c.x
delattr

__getattr__(self,name):当访问一个不存在的属性时,自动触发,默认返回值为None

正常情况下,当我们调用类的属性时,如果不存在这个属性会报错

但如果我们在类中重写了__getattr__方法,当用户访问不存在的类的属性时,python会自动调用__getattr__来获得在类中重写的属性或异常

>>>class Rectangle:
  def __init__(self,height=5):
    self.height = height
  def __getattr__(self,name):
    if name == 'width':
      width = 10
      return width
    raise AttributeError('This attribute does not exist')
>>>r = Rectangle()
>>>r.height #调用类中存在的属性,不会触发__getattr__方法
5
>>>r.width #调用类中不存在的属性,触发__getattr__方法并获得属性
10
>>>r.name #调用类中不存在的属性,触发__getattr__方法并抛出异常
AttributeError: This attribute does not exist

这里要注意一个容易产生死循环的问题,比如例子:

>>>class Rectangle:
  def __init__(self,widt = 0,height = 0):
    self.width = width #此处有给属性赋值的操作,所以会自动触发__setattr__
    self.height = height
  def __setattr__(self,name,value):
    if name == 'square':
      self.width = value
      self.height = value
    else:
      self.name = value #而在__setattr__方法中又存在赋值操作,所以产生无限递归
  def getArea(self):
    return self.width * self.height
修改方法:将else分支的语句改为super().__setattr__(name,value),此处直接调用父类的方法,免去赋值操作,就不会再产生递归
>>>r1 = Rectangle(4,5)
>>>r1.getArea()
20
>>>r1.square = 10
>>>r1.__dict__ #以列表的形式显示该对象的所有属性
{'width': 10, 'height': 10}
>>> r1.getArea()
100

Python笔记(二十六)_魔法方法_属性的魔法方法的相关教程结束。

《Python笔记(二十六)_魔法方法_属性的魔法方法.doc》

下载本文的Word格式文档,以方便收藏与打印。