python中__getattr__()和__getattribute__()方法的区别

在《编写高质量代码–改善python建议》中,看到了__getattr__()__getattribute__()方法的区别,在此一记。
__getattr__()__getattribute__() 都是用于实例属性的获取和拦截(仅对实例属性有效,非类属性,类属性通过__set____get__),__getattr__() 适用于未定义的属性,而,__getattribute__() 对于所有属性访问都会调用改方法,并且仅用于新式类。
两个区别主要如下:
1. __getattrobute__() 只要涉及到实例属性的访问就会调用该方法,如果属性不存在会抛出AttributeError 异常。
2. __getattr__() 在以下情况下调用:
2.1. 属性不在实例的__dict__中;
2.2. 属性不在其基类以及祖先类的__dict__ 中;
2.3. 出发AttributeError 异常时(不仅仅是__get_attribute__() 引发的异常,property中定义的get() 方法抛出的异常也会调用该方法。)
3. 当__getattr____getattribute__ 同时被定义时,要么显示在__getattribute__ 中调用,要么抛出AttributeError 异常,否则__getattr__ 永远不会被调用。
__getattr____getattribute__ 都是Object 类中定义的默认方法,当覆盖这些方法时需要注意几点:
1. 避免无穷递归调用;
2. 访问未定义的属性。如果__getattr__() 方法中不抛出AttributeError 异常或者显示返回一个值,则会返回None,此时可能影响到程序的实际运行预期。

class A(object):
    def __init__(self, name):
        self.name = name
        self.x = 20
    def __getattr__(self, name):
        print('calling __getattr__', name)
        if name == 'z':
            return self.x ** 2
        elif name == 'y':
            return self.x ** 3
    def __getattribute__(self, attr):
        try:
            return super(A, self).__getattribute__(attr)
        except KeyError:
            return 'default'

a = A('attribute')
print(a.name)
print(a.z)
if hasattr(a, 't'):
    c = a.t
    print(c)
else:
    print('instanc a has no attribute t')

===================================
attribute
('calling __getattr__', 'z')
400
('calling __getattr__', 't')
('calling __getattr__', 't')
None

如果t不属于实例属性,打印警告信息,否则给c赋值。按照用户的理解本来应该是输出警告信息的,可实际却输出None。因为__getattr__ 没用抛出任何异常也没有返回一个值,None被作为默认值返回并且动态添加了t属性。
另外需要注意以下两点
1) 覆盖__getattribute__方法后,任何属性的访问都会调用用户定义的__getattribute__ 方法,性能上回有损耗,比使用默认的方法要慢;
2) 覆盖的__getattr__ 方法如果能够动态处理事先未定义的属性,可以更好实现数据隐藏。
__getattribute__() 总会被调用,而__getattr__() 只有在__getattribute__() 中引发异常的情况下才会被调用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值