Python魔法方法__getattr__和__getattribute__详解
在Python中有这两个魔法方法容易让人混淆:getattr__和__getattribute。通常我们会定义__getattr__而从来不会定义__getattribute__,下面我们来看看这两个的区别。
__getattr__魔法方法
class MyClass:
def __init__(self, x):
self.x = x
def __getattr__(self, item):
print('{}属性为找到!'.format(item))
return None
>>> 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
- 首先会在对象的实例属性中寻找,找不到执行第二步
- 来到对象所在的类中查找类属性,如果还找不到执行第三步
- 来到对象的继承链上寻找,如果还找不到执行第四步
- 调用
obj.__getattr__方法,如果用户没有定义或者还是找不到,抛出AttributeError异常,属性查找失败!
class MyClass:
def __init__(self, x):
self.x = x
>>> obj = MyClass(1)
>>> obj.y
AttributeError: 'MyClass' object has no attribute 'a'
如上代码,没有定义__getattr__魔法方法,又找不到属性,就会抛出异常
__getattribute__魔法方法
当我们调用对象的属性时,首先会调用__getattribute__魔法方法。
obj.x
obj.__getattribute__(x)
如上代码,这两个代码其实是等价的。当__getattribute__查找失败,就会去调用__getattr__方法。
代码演示
class MyClass:
def __init__(self, x):
self.x = x
def __getattribute__(self, item):
print('正在获取属性{}'.format(item))
return super(MyClass, self).__getattribute__(item)
>>> obj = MyClass(2)
>>> obj.x
正在获取属性x
2
我们使用__getattribute__魔法方法时,要返回父类的方法,不然很难写对
下面代码是一个陷阱,会产生无限递归
class MyClass:
def __init__(self, x):
self.x = x
def __getattribute__(self, item):
print('正在获取属性{}'.format(item))
return self.item
>>> obj = MyClass(2)
>>> obj.x
File "xxx", line 11, in __getattribute__
print('正在获取属性{}'.format(item))
RecursionError: maximum recursion depth exceeded while calling a Python object
上面的代码看起来似乎是对的,但却调入了无限递归的陷阱,相当于
def __getattribute__(self, item):
print('正在获取属性{}'.format(item))
return self.__getattribute__(item)
要十分警惕。
另外,内置的getattr和hasattr也会触发这个魔法方法
>>> getattr(obj, 'x', None)
正在获取属性x
2
>>> hasattr(obj, 'x', None)
正在获取属性x
True
其他细节需要注意
class MyClass:
x = 999
def __init__(self, x):
self.x = x
def __getattribute__(self, item):
print('正在获取属性{}'.format(item))
return super(MyClass, self).__getattribute__(item)
上面代码中,定义了一个类属性x和一个实例属性x,这两个属性同名,根据Python语法规则,当对象获取属性x的时候,首先会在实例属性中寻找,如果找不到才回去类属性中查找
>>> obj = MyClass(2)
>>> print(obj.x)
正在获取属性x
2
>>> del obj.x #删除了实例属性x
>>> print(obj.x) #此时访问的是类属性
正在获取属性
999
这样就能印证了上面所说__getattribute__的查找顺序。通常该方法在框架中可能会用到,一般情况下无需使用。
Python魔法方法__getattr__和__getattribute__详解的更多相关文章
- python魔法方法:__getattr__,__setattr__,__getattribute__
python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ...
- python 魔法方法补充(__setattr__,__getattr__,__getattribute__)
python 魔法方法补充 1 getattribute (print(ob.name) -- obj.func())当访问对象的属性或者是方法的时候触发 class F(object): def _ ...
- python魔法方法大全
1.python魔法方法详解: python魔法方法是可以修改重载的,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而 ...
- with上下文管理 python魔法方法
with语法在Python里很常见, 主要的利好是使用代码更简洁. 常见的使用场景有: 1. 资源对象的获取与释放. 使用with可以简化try...finally ... 2. 在不修改函数代码的前 ...
- python设计模式之迭代器与生成器详解(五)
前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...
- 1. Python 魔法方法
Python 魔法方法 基础: 如果你想... 所以,你写... Python调用... 初始化一个实例 x = MyClass() x.__init__() 作为一个字符串的"官方&quo ...
- Python魔法方法总结及注意事项
1.何为魔法方法: Python中,一定要区分开函数和方法的含义: 1.函数:类外部定义的,跟类没有直接关系的:形式: def func(*argv): 2.方法:class内部定义的函数(对象的方法 ...
- python 3.x 爬虫基础---Urllib详解
python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 前言 爬虫也了解了一段时间了希望在半个月的时间内 ...
- python selenium 三种等待方式详解[转]
python selenium 三种等待方式详解 引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...
随机推荐
- RGB值得计算公式
三原色分别为:红(Red).绿(Green).蓝(Blue). 颜色值=(Red)+(Green*256)+(Blue*256*256) //由三原色值合成颜色整数值 function ColorFr ...
- Android二维码功能实现
最近二维码真是越来越火了,随便电视上.网络上.商场里,到处都是二维码.而内嵌二维码扫描功能的软件也越来越多,QQ.微信.UC浏览器等等应用都可以对着二维码扫一扫,感觉我们自己的应用里不加上二维码扫描功 ...
- SSH框架的搭建与配置文件的书写格式
通常Java Web 开发的时候,我们一般会采用三大框框架的整合来架构,这样做主要是为方便维护.但是有时候会忘了一些配文件(*.xml)的格式头,这里主要就三大框架Spring.struts.hibe ...
- Customize Acrylic Brush in UWP Applications(在UWP中自定义亚克力笔刷)
原文 Customize Acrylic Brush in UWP Applications(在UWP中自定义亚克力笔刷) Windows 10 Fall Creators Update(Build ...
- 解决关于archlinux升级至3.16.1,Xorg桌面环境无法进入的问题
[现象]有终端输入username,password后,桌面环境启动失败. [报错]log文件里显示: (EE) Fatal server error: (EE) xf86OpenConsole: V ...
- spring cloud eureka 服务端开启密码认证后,客户端无法接入问题
Eureka服务端开启密码的认证比较简单 在pom文件中加入: <dependency> <groupId>org.springframework.boot</group ...
- boost::bind应用示例
// testBind.cpp : Defines the entry point for the console application. // #include "stdafx.h&qu ...
- CefSharp中ChromiumWebBrowser打开新页面处理(_blank)
原文:CefSharp中ChromiumWebBrowser打开新页面处理(_blank) 版权声明:欢迎转载,但是请保留出处说明 https://blog.csdn.net/lanwilliam/a ...
- spring boot 集成mybatis报错Missing artifact
1. pom文件中的oracle依赖提示Missing artifact,需要手动下载并导入maven参考 oracle依赖下载地址 (ojdbc6.jar) cd到下载的ojdbc6.jar所在路径 ...
- debian安装node.js
1,先下载nodejs: # wget http://nodejs.org/dist/v0.8.7/node-v0.8.7.tar.gz 2,解压文件 # tar xvf node-v0.8.7.ta ...