class C(object):
    a = 'abc'

    def __getattribute__(self, *args, **kwargs):
        print("__getattribute__() is called")
        return object.__getattribute__(self, *args, **kwargs)

    def __getattr__(self, name):
        print("__getattr__() is called ")
        return name + " from getattr"

    def __get__(self, instance, owner):
        print("__get__() is called", instance, owner)
        return self

    def foo(self, x):
        print(x)

class C2(object):
    d = C()

"""
__get__,__getattr__和__getattribute都是访问属性的方法,但不太相同。
object.__getattr__(self, name)
当一般位置找不到attribute的时候,会调用getattr,返回一个值或AttributeError异常。

object.__getattribute__(self, name)
无条件被调用,通过实例访问属性。如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常)

object.__get__(self, instance, owner)
如果class定义了它,则这个class就可以称为descriptor。
owner是所有者的类,instance是访问descriptor的实例,如果不是通过实例访问,而是通过类访问的话,instance则为None。
(descriptor的实例自己访问自己是不会触发__get__,而会触发__call__,只有descriptor作为其它类的属性才有意义。)
(所以下文的d是作为C2的一个属性被调用)
"""

if __name__ == '__main__':
    c = C()
    c2 = C2()
    print(c.a)
    print(c.pppppp)
    c2.d        # c2是C2类的实例对象,
    print(c2.d.a)
"""
__getattribute__() is called
abc
__getattribute__() is called
__getattr__() is called
pppppp from getattr
__get__() is called <__main__.C2 object at 0x102a50860> <class '__main__.C2'>
__get__() is called <__main__.C2 object at 0x102a50860> <class '__main__.C2'>
__getattribute__() is called
abc
"""

# 通过实例对象来访问静态属性,会先执行 __getattribute__() 方法。
# 如果属性不存在,也是先走__getattribute__()方法,找不到就去get_attr()方法。

# 每次访问实现了__get__的类,都会先经过__get__函数。

# 小结:可以看出,每次通过实例访问属性,都会经过__getattribute__函数。
# 而当属性不存在时,仍然需要访问__getattribute__,不过接着要访问__getattr__。这就好像是一个异常处理函数。
# 每次访问descriptor(即实现了__get__的类),都会先经过__get__函数。
#
# 需要注意的是,当使用类访问不存在的变量是,不会经过__getattr__函数。
# 而descriptor不存在此问题,只是把instance标识为none而已。

全在玛丽

Python中__get__ ,__getattr__ ,__getattribute__用法与区别?的更多相关文章

  1. Python中__get__, __getattr__, __getattribute__的区别及延迟初始化

    本节知识点 1.__get__, __getattr__, __getattribute__的区别 2.__getattr__巧妙应用 3.延迟初始化(lazy property) 1.__get__ ...

  2. python中__get__,__getattr__,__getattribute__的区别

    __get__,__getattr__和__getattribute都是访问属性的方法,但不太相同. object.__getattr__(self, name) 当一般位置找不到attribute的 ...

  3. python3中__get__,__getattr__,__getattribute__的区别

    __get__,__getattr__和__getattribute都是访问属性的方法,但不太相同. object.__getattr__(self, name) 当一般位置找不到attribute的 ...

  4. python 中__setattr__, __getattr__,__getattribute__, __call__使用方法

    object._getattr_(self, name) 拦截点号运算.当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法.如果继承树可以找到该属性,则不调用此方法 实例in ...

  5. Python中eval与exec用法的区别

    Python中eval,exec这两个函数有着相似的输入参数类型和执行功能,因此在用法上经常出现混淆,以至经常用错,程序易抛出错误.下面主要通过这两个函数的语法来阐述区别,并用例子来进一步说明. 首先 ...

  6. python中sort和sorted用法的区别

    Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列 一,最简单的排序 1.使用sort排序 my_list = [3 ...

  7. Python中sorted()方法的用法

    Python中sorted()方法的用法 2012-12-24 22:01:14|  分类: Python |字号 订阅 1.先说一下iterable,中文意思是迭代器. Python的帮助文档中对i ...

  8. python中import和from...import...的区别

    python中import和from...import...的区别: 只用import时,如import xx,引入的xx是模块名,而不是模块内具体的类.函数.变量等成员,使用该模块的成员时需写成xx ...

  9. Linux中yum和apt-get用法及区别

    Linux中yum和apt-get用法及区别   一般来说著名的linux系统基本上分两大类:   1.RedHat系列:Redhat.Centos.Fedora等   2.Debian系列:Debi ...

随机推荐

  1. 谷歌浏览器Chrome developer tool详细介绍

    http://www.cr173.com/html/19114_4.html 第 4 页 js调试源码控制面板 5 源码控制面板(js调试) Javascript的调试,基本上是通过源码控制面板和命令 ...

  2. Mysql-数据库及数据表结构和操作

    1.数据库系统:数据库系统是用来维护和管理数据库的系统工具,数据库系统拥有自己的用户名和密码 1.1.显示该系统中的数据库:Show databases; 1.2.创建数据库:Create datab ...

  3. ABAP和Java单例模式的攻防

    ABAP CLASS zcl_jerry_singleton DEFINITION PUBLIC FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES i ...

  4. 使用EventLog组件读写事件日志

    实现效果: 知识运用: Eventlog类的SourceExists方法 //确定指定的事件源是否已在本地计算机注册 public static bool  SourceExists(string s ...

  5. openstack rocky kolla docker

    https://docs.openstack.org/kolla-ansible/latest/user/quickstart.html

  6. Java的引用StrongReference、 SoftReference、 WeakReference 、PhantomReference

    1. Strong Reference StrongReference 是 Java 的默认引用实现,  它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收 @Te ...

  7. SQL 隔离级别

    在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的.较低级别的隔离通常可以执行更高的并发,系统的开销也更低. 简单的介绍四种隔离级别 ...

  8. C++内存溢出和内存泄漏?

    1.内存溢出 内存溢出是指程序在申请内存时没有足够的内存空间供其使用.原因可能如下: (1)内存中加载的数据过于庞大: (2)代码中存在死循环: (3)递归调用太深,导致堆栈溢出等: (4)内存泄漏最 ...

  9. 在ubuntu中用命令安装iperf

    Iperf的安装要换成阿里的源 sudo add-apt-repository "ppa:patrickdk/general-lucid" sudo apt-get update ...

  10. C#数组删除元素

    一.C#数组删除元素 在C#中,只能在动态数组ArrayList类中对数组执行删除元素的操作.因为动态数组是一个可以改变数组长度和元素个数的数据类型. 示例: using System;using S ...