Python学习笔记 魔法方法之__getattr__、__getattribute__解析

__getattr__

当__getattribute__没有手动定义时,若用户访问了不存在的对象,或者对象的属性不存在时,调用此函数。

__getattribute__

定义此方法后,优先调用。

几个例子:

1. __getattr____getattribute__的调用顺序
class A:
    def __getattr__(self, item):
        print(1)
    def __getattribute__(self, item):
        print(2)
    def __setattr__(self, key, value):
        print(3)
    def __delete__(self, instance):
        print(4)

a = A()
a.x
a.x = 10
a.x
print(a.x)

结果

2
3
2
2
None

逐步分析:首先,由于类中没有x,所以当运行a.x的时候,系统会调用__getattribute__(self, item)函数,或许会有人疑惑:“哎?为什么x这个属性明明没有设定,但却调用了__getattribute__(self, item)?为什么没有调用__getattr__?”
这就是第一个重点了,当用户自己定义了__getattribute__(self, item)函数,那么就会无条件(不管有没有这个属性)优先调用__getattribute__(self, item)函数了。
那么例1中的代码就一目了然了,首先调用了__getattribute__(self, item),打印2,随后调用__setattr__(self, key, value),打印3,由于__setattr__(self, key, value)并没有规定返回值,所以x并没有被定义,a.x相当于None

2. 为__getattribute__(self, item)设定返回值
class A:
    def __getattr__(self, item):
        print(1)
    def __getattribute__(self, item):
        print(2)
        return super().__getattribute__(item)
    def __setattr__(self, key, value):
        print(3)
        return super().__setattr__(key, value)
    def __delete__(self, instance):
        print(4)

a = A()
a.x
a.x = 10
a.x
print(a.x)

结果

2
1
3
2
2
10

分析:为什么这里会打印出1这个值呢?即为什么函数__getattr__(self, item)被调用了呢?仔细一看,原来对__getattribute__(self, item)添加了返回值

def __getattribute__(self, item):
        print(2)
        return super().__getattribute__(item)

也就是说,这次执行代码的时候,系统还是优先调用__getattribute__(self, item),打印2,随后调用super().__getattribute__(item),由于找不到x,系统就会按照object里的方法__getattribute__(self, item)调用__getattr__(self, item),然后打印1

你可能感兴趣的:(Python学习笔记 魔法方法之__getattr__、__getattribute__解析)