当前位置: 首页 > 图灵资讯 > 行业资讯> Python魔法方法之__getattr__和getattribute

Python魔法方法之__getattr__和getattribute

发布时间:2025-10-21 21:25:19

这两种魔法方法在Python中很容易混淆:__getattr__和getattribute。通常我们会定义__getattr__而且从来不定义getattribute,下面我们来看看这两者的区别。

__getattr__魔法方法

classMyClass:
def__init__(self,x):
self.x=x
def__getattr__(self,item):
print('{}属性为找到!'.format(item))
returnNone
>>>obj=MyClass(1)
>>>obj.x
1
>>>obj.y
发现y属性!
None

我们定义MyClass类,设置x的实例属性,值为1。obj是这类实例,获取obj.x返回1,获得obj.y发现属性找不到,因为obj的实例变量不包含y,找不到属性时会调用__getattr__方法。

**调用__getattr__详细流程如下:**

obj.attr

1.首先会在对象的实例属性中找到,找不到执行的第二步

2.来到对象所在的类中查找类属性,如果找不到执行第三步

3.来到对象的继承链寻找,如果找不到执行第四步

4.调用obj.__getattr__方法,如果用户没有定义或仍然找不到,抛出Attributeerror异常,属性搜索失败!

classMyClass:
def__init__(self,x):
self.x=x
>>>obj=MyClass(1)
>>>obj.y
AttributeError:'MyClass'objecthasnoattribute'a'

以上代码未定义___getattr__魔法方法,如果找不到属性,就会抛出异常。

相关推荐:Python视频教程

__getattribute__魔法方法

当我们调用对象的属性时,我们将首先调用__getattribute__魔法方法。

obj.x
obj.__getattribute__(x)

以上代码,这两个代码实际上是等价的。当__getattribute__如果发现失败,会调用__getattr__方法。

代码演示

classMyClass:
def__init__(self,x):
self.x=x
def__getattribute__(self,item):
print('属性{}'正在获取;.format(item))
returnsuper(MyClass,self).__getattribute__(item)
>>>obj=MyClass(2)
>>>obj.x
属性x正在获取
2

使用_____getattribute__魔法方法时,回到父亲的方法,否则很难写对。下面的代码是一个陷阱,会产生递归。

classMyClass:
def__init__(self,x):
self.x=x
def__getattribute__(self,item):
print('属性{}'正在获取;.format(item))
returnself.item

>>>obj=MyClass(2)
>>>obj.x
File"xxx",line11,in__getattribute__
print('属性{}'正在获取;.format(item))
RecursionError:maximumrecursiondepthexceededwhilecallingaPythonobject

上面的代码似乎是对的,但它们被调入递归陷阱,相当于

def__getattribute__(self,item):
print('属性{}'正在获取;.format(item))
returnself.__getattribute__(item)

非常警惕。

此外,内置的getattr和hasatr也会触发这种魔法方法。

>>>getattr(obj,'x',None)
属性x正在获取
2
>>>hasattr(obj,'x',None)
属性x正在获取
True

需要注意其他细节

classMyClass:
x=999

def__init__(self,x):
self.x=x
def__getattribute__(self,item):
print('属性{}'正在获取;.format(item))
returnsuper(MyClass,self).__getattribute__(item)

在上述代码中,定义了类属性x和实例属性x,这两个属性是同名的。根据Python语法规则,当对象获得属性x时,它将首先在实例属性中找到,如果找不到,则返回类属性。

>>>obj=MyClass(2)
>>>print(obj.x)
属性x正在获取
2
>>>delobj.x#删除实例属性x
>>>print(obj.x)#此时访问的是类属性
正在获得属性
999

这样就可以证实上面提到的__getattribute__搜索顺序。通常这种方法可以在框架中使用,一般不需要使用。

相关文章

Python魔法方法之__getattr__和getattribute

Python魔法方法之__getattr__和getattribute

2025-10-21
python安装MongoDB

python安装MongoDB

2025-10-21
Python运算符优先级

Python运算符优先级

2025-10-21
Python如何把类当做字典来访问

Python如何把类当做字典来访问

2025-10-21
Python列表推导式(for表达式)及用法

Python列表推导式(for表达式)及用法

2025-10-21
浅谈Python类命名空间

浅谈Python类命名空间

2025-10-21