Python __getattr__ __getattribute__ __setattr__

__getattr__

如果某类定义了__getattr__,同时系统在该类对象的实例字典中又找不到待查询的属性,系统就会调用这个方法,这种行为非常适合无结构数据的按需访问。

class A:
    def __init__(self):
            self.name = 'Tom'
    def __getattr__(self,name):
            setattr(self, name, name)
            return "can not find %s attr" %name
>>> a = A()
>>> a.name									# name属性本身在实例字典里,所以绝对不会触发__getattr__
'Tom'
>>> a.age									# age 会触发__getattr__,又调用setattr方法放入属性字典
'can not find age attr'
>>> 
>>> a = A()
>>> a.__dict__
{'name': 'Tom'}
>>> a.name
'Tom'
>>> a.age
'can not find age attr'
>>> a.__dict__
{'name': 'Tom', 'age': 'age'}

__getattribute__

程序每次访问对象属性时,Python系统都会调用这个特殊的方法,即使属性字典里面已经有了改属性,也依然会触发__getattribute__。

class B(object):
    def __init__(self):
        self.name = 'Frank'
    def __getattribute__(self, name):
        print('Called __getattribute__(%s)' % name)
        try:
            return super().__getattribute__(name)
        except AttributeError:
            setattr(self, name, name)
            return "can not find %s attr" %name
>>> b = B()
>>> b.name
Called __getattribute__(name)
'Frank'
>>> b.age
Called __getattribute__(age)
'can not find age attr'
>>> b.age
Called __getattribute__(age)
'age'
如果类还定义了__getattr__方法,除非__getattribute__调用它或者出现AttributeError错误,否则__getattr__方法不会被调用。
class B(object):
    def __init__(self):
        self.name = 'Frank'
    def __getattribute__(self, name):
        print('Called __getattribute__(%s)' % name)
        super().__getattribute__(name)
    def __getattr__(self, name):
        print('Called __getattr__(%s)' % name)
>>> b = B()
>>> b.a
Called __getattribute__(a)
Called __getattr__(a)
__getattribute__方法下应该避免使用self.attr访问属性,否则会出现无限递归。如要要访问实例属性,应该直接通过super()来做。
class B(object):
    def __init__(self):
        self.name = 'Frank'
    def __getattribute__(self, name):
#        return self.__dict__['name']				#导致无限递归
        return super().__getattribute__(name)		#正常
>>> b = B()
>>> b.name


__setattr__ 
只要对实例属性赋值,无论是直接赋值,还是通过内置的setattr赋值,都会触发__setattr__方法。__setattr__下还有self.attr的赋值操作就会出现无线递归的调用__setattr__的情况。一般情况都还是继承

class C:
    def __setattr__(self, name, value):
        print('Called __setattr__(%s, %r)' % (name, value))
        super().__setattr__(name, value)
>>> c = C()
>>> c.a = 1
Called __setattr__(a, 1)
>>> c.a
1
>>> c.b = 2
Called __setattr__(b, 2)
>>> setattr(c,'d',2)
>>> c.__dict__
{'a': 1, 'd': 2, 'b': 2}
hasattr函数来判断对象是否拥有相关的属性,并用内置的getattr函数来获取属性值。这些函数会先在实例字典中搜索待查询的属性。然后再调用__getattr__

和__getattribute__函数是什么?它们的作用是什么? __getattr__是Python中的一个特殊方法,用于在访问一个不存在的属性时触发。当我们尝试访问一个对象的属性,而该属性不存在时,Python会调用__getattr__方法来处理这个请求。可以在__getattr__方法中自定义对不存在属性的处理逻辑,比如返回默认值或抛出异常。 __setattr__是Python中的另一个特殊方法,用于在给对象的属性赋值时触发。当我们对一个对象的属性进行赋值时,Python会调用__setattr__方法来处理这个赋值操作。可以在__setattr__方法中自定义对属性赋值的行为,比如进行一些额外的操作或进行属性值的验证。需要注意的是,在__setattr__方法中对属性进行赋值时,应该调用父类的__setattr__方法来避免引起无限递归。 __getattribute__是Python中的另一个特殊方法,用于获取对象的属性值。当我们尝试获取一个对象的属性时,不论这个属性是否存在,Python都会调用__getattribute__方法来处理这个请求。可以在__getattribute__方法中自定义对属性的获取行为,比如进行一些额外的操作或返回特定的属性值。需要注意的是,在__getattribute__方法内部访问属性时,应该使用super().__getattribute__方法来避免引起无限递归。 总结一下: - __getattr__用于处理访问不存在属性的情况,可以自定义对不存在属性的处理逻辑。 - __setattr__用于处理属性赋值的情况,可以自定义对属性赋值的行为。 - __getattribute__用于获取属性的值,可以自定义对属性获取的行为。 参考资料: 属性相关:__getattr__函数、__setattr__函数、__getattribute__函数、__setattribute__函数和__dir__函数: - 知乎 (zhihu.com) 引用中的代码示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值