鱼C论坛

 找回密码
 立即注册
查看: 685|回复: 15

[已解决]__get__方法与__getattribute__方法

[复制链接]
发表于 2020-5-3 08:17:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
想要问一下__get__方法与__getattribute__方法的区别


                               
登录/注册后可看大图
class C:
       def __get__(self,insatnace,owner):
            print('调用get魔法方法')
class B:
        x=C()
        def __getattribute__(self):
                 print('调用getattribute魔法方法')

#主程序
b=B()
b.x

显示出来调用的是B的属性访问的相关魔法方法,所以说:__get__方法与__getattribute__方法到底怎么区别的,什么时候会触发__get__方法,是不是在没有__getattribute__方法的情况下?因为即使C是一个描述符类,但是当B的__getattribute__方法重写后,它是会调用B的__getattribute__方法而不是自动调用C类的__get__方法。
最佳答案
2020-5-3 14:20:34
不多bb,看看这段程序你就懂了
>>> class C:
        def __get__(self,instance,owner):
                print('get')

               
>>> class B:
        def __getattribute__(self,name):
                print('getattribute')
                return super().__getattribute__(name)
        c=C()

       
>>> b=B()
>>> b.c
getattribute
get
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-5-3 09:21:25 | 显示全部楼层
__getattr__ 和 __setattr__ 方法,把未定义的属性获取和所有的属性赋值指向通用的处理器方法。
__getattr__ 和__getattribute__ 操作符重载方法提供了拦截类实例的属性获取的另一种方法。就像特性和描述符一样,它们也允许我们插入当访问属性的时候自动运行的代码。
__getattr__ 针对未定义的属性运行——也就是说,属性没有存储在实例上,或者没有从其类之一继承。
__getattribute__ 针对每个属性,因此,当使用它的时候,必须小心避免通过把属性访问传递给超类而导致递归循环。

这些方法通常都容易使用,它们唯一复杂的部分就是潜在的循环(即递归)。由于__getattr__仅针对未定义的属性调用,所以它可以在自己的代码中自由地获取其他属性。然而,由于__getattribute__ 和 __setattr__ 针对所有的属性运行,因此,它们的代码要注意在访问其他属性的时候避免再次调用自己并触发一次递归循环。

摘抄自《Python 学习手册 (第四版)》第953、954、955页

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 09:56:46 | 显示全部楼层
xiangjianshinan 发表于 2020-5-3 09:21
__getattr__ 和 __setattr__ 方法,把未定义的属性获取和所有的属性赋值指向通用的处理器方法。
__getattr ...

baby 有一个地方是:我问的是__get__方法嘿~不是_getattr_嘿
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 10:02:33 | 显示全部楼层
本帖最后由 Twilight6 于 2020-5-3 10:29 编辑
liliya 发表于 2020-5-3 09:56
baby 有一个地方是:我问的是__get__方法嘿~不是_getattr_嘿


__get__是描述符的属性被访问被调用、__getattribute__是类属性被访问时候被调用
当我们用或者实例来调用该属性时,会返回__get__函数的结果。
当一个函数定义了__get__方法,那么这个函数就是描述符(descriptor)。

看~:
class C:
    x = 123456
    def __get__(self, insatnace, owner):
        print('调用__get__魔法方法')
    def __getattribute__(self, item):
        print('调用__getattribut__方法')

class B:
    a = C()


a = C()
b = B()
a.x
b.a.x  # 当一般位置找不到属性的时候,会调用getattr,返回一个值或AttributeError异常
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 10:11:06 | 显示全部楼层
'''
描述符可能是分配给对象的一个类属性,该对象带有一个 __get__ 方法,当引用或获取该属性的时候自动运行该方法
'''
class Descriptor(object):
    def __get__(self, instance, owner): ...
class Subject:
    attr = Descriptor()

X = Subject()
X.attr # Roughly runs Descriptor.__get__(Subject.attr, X, Subject)

'源自《Python 学习手册(第四版)》第1000页'

因为我也不是很懂,学到这里后,卡壳,学不下去啦!!!

就东看看,西瞅瞅地!!! 一起加油~~~~~~~~~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 10:36:15 | 显示全部楼层
Twilight6 发表于 2020-5-3 10:02
__get__是描述符的属性被访问被调用、__getattribute__是类属性被访问时候被调用
当我们用类或者实例 ...

这个我知道,现在我的问题是,你看我的例子,我这个类对象(A)拥有的属性中有一个属性x它是具有描述符类(B)的,但我这个类对象(A)自身具有__getattribute__/__getattr__方法,那么我在访问这个类对象的属性的时候(a.x)前一节课不是学了吗,我们在访问类的属性的时候会自动先去调用__getattribute__然后调用__getattr__方法。那么我确定a是有x这个属性的,那么他会去调用A的__getattribute__方法,而不是描述符类B的__get__方法。这里面是存在什么优先级的问题嘛??因为单独语句:a.x,到底是使用__getattribute__还是B的__get__。显然运行的结果是优先调用A的__getattribute__方法。这里面是不是有什么优先级机制是我不知道的。问题在于这个。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 10:45:42 | 显示全部楼层
本帖最后由 Twilight6 于 2020-5-3 10:54 编辑
liliya 发表于 2020-5-3 10:36
这个我知道,现在我的问题是,你看我的例子,我这个类对象(A)拥有的属性中有一个属性x它是具有描述符类 ...


不是优先级问题,当你直接单独a.x 时候是不可能调用__get__方法的

get方法是要在一个类实例里存在这另一个类(这个类里面定义了__get__方法,也称描述符),从这个a实例去访问此实例中的另一个实例(描述符)中的属性,才会调用get。


(上面可能存在很多语法错误,因为我只是把我的理解说出,但是大体上意思就是这样)
class A:
    x = 666
    def __get__(self, instance, owner):
        print('get~')
    def __getattribute__(self, item):
        print('getattribute')
class B:
    a = A()

a = A()
b = B()

a.x  # 通过实例访问属性,都会经过__getattribute__函数。而当该属性不存在时,仍会先访问__getattribute__,但是之后还会接着要访问__getattr__ ,弹出异常。 
b.a.x  # 每次访问描述符(descriptor)(即定义了__get__的类),都会先经过__get__函数。



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 10:59:27 | 显示全部楼层
Twilight6 发表于 2020-5-3 10:45
不是优先级问题,当你直接单独a.x 时候是不可能调用__get__方法的

get方法是要在一个类实例里存在这 ...
class C:
       def __get__(self,insatnace,owner):
            print('调用get魔法方法')
class B:
        x=C()
        def __getattribute__(self):
                 print('调用getattribute魔法方法')

#主程序
b=B()
b.x

baby你还没有懂我的意思。你看这个里面,我x具有描述符类A对吧。在我没有定义B类的 __getattribute__(self)方法的时候,b.x是会去调用A这个描述符类的__get__方法的。你可以运行下,是这样的。现在我定义了B类的__getattribute__(self)方法,我再去b.x它会调用B类的__getattribute__(self)而不是A类的__get__方法了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 11:02:28 | 显示全部楼层
本帖最后由 Twilight6 于 2020-5-3 11:04 编辑
liliya 发表于 2020-5-3 10:59
baby你还没有懂我的意思。你看这个里面,我x具有描述符类A对吧。在我没有定义B类的 __getattribute__ ...


。。。你函数从开始都是错的,__getattribute__参数要两
    def __getattribute__(self, item):

运行结果

运行结果
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 11:05:38 | 显示全部楼层
Twilight6 发表于 2020-5-3 11:02
。。。你函数从开始都是错的,__getattribute__参数要两

这不是重点呀baby,几个参数不重要啊,我没有用name这个东西做任何事情,我加不加它不会影响结果。我这个只是打印了一句调用这个函数,必须要有name的时候是因为我在return 语句中要返回这个值,我现在只是想看调用这个函数就可以了,跟那个没关系的,无所谓的,如果说函数是错的,那么他都不可能打印出来这个语句。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 11:07:32 | 显示全部楼层
liliya 发表于 2020-5-3 11:05
这不是重点呀baby,几个参数不重要啊,我没有用name这个东西做任何事情,我加不加它不会影响结果。我这个 ...

baby,不加这个参数会报错啊?虽然不重要但是要拿个正常的代码吧?我只是提醒你,总觉得你问别人问题像别人欠你一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 11:07:32 | 显示全部楼层
Twilight6 发表于 2020-5-3 11:02
。。。你函数从开始都是错的,__getattribute__参数要两
    def __getattribute__(self, item):
             return self.item
你要加这个item参数是因为你在return语句中要去用到它,我只是在这里看一下会不会调用这个函数而已。我不需要他做任何事情,我只是看他会进入到哪个函数而已。我不需要它具体返回这个参数的值。你可以去把我函数改了,改了之后还是一样的效果。这个无所谓的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 11:12:08 | 显示全部楼层
Twilight6 发表于 2020-5-3 11:07
baby,不加这个参数会报错啊?虽然不重要但是要拿个正常的代码吧?我只是提醒你,总觉得你问别人问题像别 ...

只是讨论而已,只是表达不是这个影响的,没有别的意思。谢谢你回答问题,就可能我个性比较直,sorry。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 11:16:38 | 显示全部楼层
liliya 发表于 2020-5-3 11:12
只是讨论而已,只是表达不是这个影响的,没有别的意思。谢谢你回答问题,就可能我个性比较直,sorry。

算了,是我自作多情、愚笨听不懂你题意,在这浪费自己的时间去解些自己解不开的题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 14:20:34 | 显示全部楼层    本楼为最佳答案   
不多bb,看看这段程序你就懂了
>>> class C:
        def __get__(self,instance,owner):
                print('get')

               
>>> class B:
        def __getattribute__(self,name):
                print('getattribute')
                return super().__getattribute__(name)
        c=C()

       
>>> b=B()
>>> b.c
getattribute
get
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-21 07:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表