这里的属性即包括属性变量,也包括属性方法。即类的变量和方法。
  当访问某个实例属性时, 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. linux中忘记root密码解决方案

    方法一: 如果用户具有sudo权限,那么直接可以运行如下命令: #sudo su root #passwd #更改密码 或者直接运行sudo passwd root命令就可以直接更改root密码. 有 ...

  2. 搭建简单的CGI应用程序

    原文来源于<核心编程3>第10章web编程 一.静态文件+脚本文件 1.首先开启cgiweb服务器 python2 -m CGIHTTPServer 8000 看到如下反应 2.服务器目录 ...

  3. Codeforces Round #278 (Div. 1) B - Strip dp+st表+单调队列

    B - Strip 思路:简单dp,用st表+单调队列维护一下. #include<bits/stdc++.h> #define LL long long #define fi first ...

  4. DER编码简介

    概念:DER是BER的子集,它为每一个ASN.1类型定义一种唯一的编码方案. DER与BER的区别:DER在BER的基础上增加了如下限制:长度小于等于127,必须使用短型长度表示法.长度大于127,必 ...

  5. php计算两个坐标(经度,纬度)之间距离的方法

    本文实例讲述了php计算两个坐标(经度,纬度)之间距离的方法.分享给大家供大家参考.具体如下: 这里使用php计算两个坐标(经度,纬度)之间的距离,返回结果为米或者千米 function distan ...

  6. Void运算符 与 undefined类型

    void 运算符 对给定的表达式进行求值,然后返回 undefined. 何为求值,就是执行之后的表达式. 我们最常见的就是 <a href="javascript: void(0)& ...

  7. docker chown: changing ownership of '/var/lib/XXX': Permission denied

    Links: 1.entos7下docker Permission denied 2.查看 SELinux状态及关闭SELinux 方法: 1.查看SELinux状态sestatus -vgetenf ...

  8. java 错误:无法找到或装入主类

    1. 删除找不到的jar 2. 删除src以外的文件夹

  9. 八步详解Hibernate的搭建及使用

    本文通过了八个步骤以及一些实例添加用户来介绍Hibernate的搭建和使用,真切的介绍了hibernate的基本用法,其中好多优点等待我们自己去发现,比如hibernate中的缓存机制,映射方案. 1 ...

  10. Bakery CodeForces - 707B (最短路的思路题)

    Masha wants to open her own bakery and bake muffins in one of the n cities numbered from 1 to n. The ...