这里的属性即包括属性变量,也包括属性方法。即类的变量和方法。
  当访问某个实例属性时, getattribute会被无条件调用,如未实现自己的getattr方法,会抛出AttributeError提示找不到这个属性,如果自定义了自己getattr方法的话,方法会在这种找不到属性的情况下被调用,比如上面的例子中的情况。所以在找不到属性的情况下通过实现自定义的getattr方法来实现一些功能是一个不错的方式,因为它不会像getattribute方法每次都会调用可能会影响一些正常情况下的属性访问
 
  使用这几个方法可以实现拦截器啥、动态代理、统一log等功能。
 
  举例:
  1、使用__getattribute__实现统一的打印日志功能。使用__getattribute__方法拦截了属性和方法的访问。__getattribute__只有在新式类中才能使用。
  

# -*- coding: utf- -*-
class Fjs(object):
def __init__(self, name):
self.name = name def hello(self):
print "said by : ", self.name def __getattribute__(self, item):
print "访问了特性:" + item
return object.__getattribute__(self, item) fjs = Fjs("fjs")
print fjs.name
fjs.hello()

输出:

访问了特性:name
fjs
访问了特性:hello
said by : 访问了特性:name
fjs

  2、这里通过__getattr__方法,将所有的特性的访问都路由给了内部的fjs对象

# -*- coding: utf- -*-
class Fjs(object):
def __init__(self, name):
self.name = name def hello(self):
print "said by : ", self.name def fjs(self, name):
if name == self.name:
print "yes"
else:
print "no" class Wrap_Fjs(object):
def __init__(self, fjs):
self._fjs = fjs def __getattr__(self, item):
if item == "hello":
print "调用hello方法了"
elif item == "fjs":
print "调用fjs方法了"
return getattr(self._fjs, item) fjs = Wrap_Fjs(Fjs("fjs"))
fjs.hello()
fjs.fjs("fjs")

输出:

调用hello方法了
said by : fjs
调用fjs方法了
yes

  3、使用类的继承实现。则不会路由,子类直接继承了父类的属性和方法

# -*- coding: utf- -*-
class Fjs(object):
def __init__(self, name):
self.name = name def hello(self):
print "said by : ", self.name def fjs(self, name):
if name == self.name:
print "yes"
else:
print "no" class Wrap_Fjs(Fjs):
def __init__(self, fjs):
self._fjs = fjs def __getattr__(self, item):
if item == "hello":
print "调用hello方法了"
elif item == "fjs":
print "调用fjs方法了"
return getattr(self._fjs, item) fjs = Wrap_Fjs(Fjs("fjs"))
fjs.hello()
fjs.fjs("fjs")

输出:

said by :  fjs
yes

  4、猜一下结果,理解其妙用

# 例子在原来的基础上简化了一下,排除依赖和干扰,详细参见原项目
class UrlGenerator(object):
def __init__(self, root_url):
self.url = root_url def __getattr__(self, item):
if item == 'get' or item == 'post':
print self.url
return UrlGenerator('{}/{}'.format(self.url, item)) url_gen = UrlGenerator('http://xxxx')
url_gen.users.show.get

  5、通过转换,可以像访问属性一样访问dict中的键值对

class ObjectDict(dict):
def __init__(self, *args, **kwargs):
super(ObjectDict, self).__init__(*args, **kwargs) def __getattr__(self, name):
value = self[name]
if isinstance(value, dict):
value = ObjectDict(value)
return value if __name__ == '__main__':
od = ObjectDict(asf={'a': }, d=True)
print od.asf, od.asf.a # {'a': }
print od.d # True
 
参考:
1、https://www.jianshu.com/p/885d59db57fc
2、https://www.cnblogs.com/xybaby/p/6280313.html

Python的__getattribute__ vs __getattr__的妙用的更多相关文章

  1. python魔法函数__dict__和__getattr__的妙用

    python魔法函数__dict__和__getattr__的妙用 __dict__ __dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值. 既然__dict__是个字典那么我们就 ...

  2. python魔法方法:__getattr__,__setattr__,__getattribute__

    python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ...

  3. python基础---- __getattribute__----__str__,__repr__,__format__----__doc__----__module__和__class__

    目录: 一. __getattribute__ 二.__str__,__repr__,__format__ 三.__doc__ 四.__module__和__class__ 一. __getattri ...

  4. python魔法函数之__getattr__与__getattribute__

    getattr 在访问对象的属性不存在时,调用__getattr__,如果没有定义该魔法函数会报错 class Test: def __init__(self, name, age): self.na ...

  5. python __getattribute__、__getattr__、__setattr__详解

    __getattribute__ 官方文档中描述如下: 该方法可以拦截对对象属性的所有访问企图,当属性被访问时,自动调用该方法(只适用于新式类).因此常用于实现一些访问某属性时执行一段代码的特性. 需 ...

  6. Python __getattribute__ vs __getattr__

    # 例子在原来的基础上简化了一下,排除依赖和干扰,详细参见原项目 class UrlGenerator(object): def __init__(self, root_url): self.url ...

  7. __getattribute__()、__getattr__()、__setattr__()、__delattr__()

    访问顺序: 实例的__getattribute__().Descriptor的__get__().实例的__dict__.只读Descriptor的__get__().实例的__getattr__() ...

  8. python中的__dict__,__getattr__,__setattr__

    python class 通过内置成员dict 存储成员信息(字典) 首先用一个简单的例子看一下dict 的用法 class A(): def __init__(self,a,b): self.a = ...

  9. Python的__getattribute__二三事

    本来以为自己对__getattribute__已经比较了解了,结果用到的时候,才发现有一些知识点之前一直没有真正弄明白,记录如下(针对python3,python2差异较大): object类有__g ...

随机推荐

  1. vim 图册

    网上看到的一些图,感觉不错,分享一下 我现在感觉配置文件,很多没有必要,反而很花哨,但是这些基础的东西,反而很高效,实在 VIM的列编辑操作 删除列 1.光标定位到要操作的地方. 2.CTRL+v 进 ...

  2. python部分内容存档

    笨办法学python. 1 Ec6字符串和文本... 1 ec7. 1 ec8. 1 Ec9. 1 Ec10 转义字符... 1 Ec11提问... 1 raw_input和input的区别... 1 ...

  3. Error: Exception was raised when calling event-notify Vuser function in extension parameng.dll: System Exceptions: EXCEPTION_ACCESS_VIOLATION

    解决方法:在C 盘新建一个TEMP目录,把环境变量TMP,TEMP的值设置成环境变量,重启计算机

  4. HTML5 Video/Audio播放本地文件

    这段时间经常看到开发者在反复询问同一个问题,为什么通过设置src属性,不能播放本地的媒体文件?例如video.src=”D:\test.mp4”. 这是因为浏览器中的JavaScript不能直接直接访 ...

  5. 解决centOS7的IP为127.0.0.1,无法用Xshll链接问题

    对于linux不熟悉的我, 安装完centOS7后好多坑,走一步卡一步,记得之前安装其他版本没这么多事.安装完后用ifconfig查看IP,竟然是127.0.0.1,这我就不知道怎么用Xshell链接 ...

  6. Java中的强引用,软引用,弱引用

    作者:winterSunshine链接:https://www.zhihu.com/question/37401125/answer/100981172来源:知乎著作权归作者所有.商业转载请联系作者获 ...

  7. python魔法方法-自定义序列详解

    自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等). 如果要实现这个功能,就要遵循 python ...

  8. FastReport.Net使用:[18]形状(Shape)控件用法

    FastReport中,如果要画一张漂亮的报表,经常会画些形状控件来美化?那么如何用好形状(Shape)控件呢? 形状的5种类型 在工具栏的图形控件下拉菜单中有5种类型(矩形.圆角矩形.椭圆形.三角形 ...

  9. 【BZOJ 3443】 3443: 装备合成 (离线+线段树)

    3443: 装备合成 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 63  Solved: 31 Description [背景]     lll69 ...

  10. 数据仓库之父——Bill Inmon(转载)

    从此处转载 http://blog.sina.com.cn/s/blog_615f9dba0100f67p.html 比尔·恩门(Bill Inmon),被称为数据仓库之父,最早的数据仓库概念提出者, ...