Python魔术方法 __getattr__、__getattribute__使用详解

5,616 阅读2分钟

Python魔术方法 getattr、__getattribute__使用详解

  • _getattr_(self,attr)
    • 触发时机:获取不存在的对象成员时触发
    • 参数:1、接收当前对象的self,2、获取成员名称的字符串
    • 返回值: 必须有值
    • 作用:为访问不存在的属性设置值
    • 注意:_getattribute_()无论何时都会在_getattr_()之前触发,触发了_getattribute_()有返回值就不会在触发_getattr_()了
  • _getattribute_(self,attr)
    • 触发时机:使用对象成员时触发,无论成员是否存在
    • 参数:1、接收当前对象的self,2、获取成员名称的字符串
    • 返回值: 必须有值
    • 作用:在具有封装操作(私有化时),为程序开部分访问权限使用
class Human:
    # 成员属性
    name = None
    sex = None
    age = None
    
    # 成员方法
    # 对象初始化
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    # 访问不存在成员时触发
    def __getattr__(self,attr):
        print('触发了__getattr__(),要访问对象的{}成员'.format(attr))
        return '访问成员不存在'
        pass
    # 访问成员的时候触发
    def __getattribute__(self,attr):
        print('触发了__getattribute__(),要访问对象的{}成员'.format(attr))
        # 一定不能使用self.__getattribute__(self,attr),否则会导致递归死循环,使用object的方法访问
        if attr in ('name','sex','age','height','test'):
            return object.__getattribute__(self,attr)
        else :
            return '返回默认值'
    # 测试方法
    def test(self):
        print('调用测试方法test')
# 实例化Test类,分别访问对象的name(存在的成员属性)、test(存在的成员方法)、wight(不存在的成员属性),验证结果
xm = Human('小明','男',18)
# name(存在的成员属性),触发__getattribute__()方法正常返回,就不会再触发__getattr__()方法了
print(xm.name)
触发了__getattribute__(),要访问对象的name成员
小明
# test(存在的成员方法),调用和访问成员方法都会触发__getattribute__()方法
print(xm.test)
print()
xm.test()
触发了__getattribute__(),要访问对象的test成员
<bound method Human.test of <__main__.Human object at 0x0000018D59C5B080>>

触发了__getattribute__(),要访问对象的test成员
调用测试方法test
# wight(不存在的成员属性)
# 虽然wight不存在,但是在__getattribute__(self,attr)方法中对于访问xm.wight时设置返回‘返回默认值’
# __getattribute__(self,attr)正常返回时并没有触发__getattr__(self,attr)方法
print(xm.wight)


print('\n####################################################################\n')


# 但是当访问height成员属性时,__getattribute__(self,attr)方法并没有直接返回,
# 而是使用object.__getattribute__(self, attr)访问对象对的成员,从而触发了__getattr__()
print(xm.height)
触发了__getattribute__(),要访问对象的wight成员
返回默认值

####################################################################

触发了__getattribute__(),要访问对象的height成员
触发了__getattr__(),要访问对象的height成员
访问成员不存在