杨东明 发表于 2021-7-20 16:45:58

请问这里b.a.x为啥会报错。。?

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__函数。

kogawananari 发表于 2021-7-20 16:45:59

class A:
    x = 666
    def __get__(self, instance, owner):
      print('get~')
      return self
    def __getattribute__(self, item):
      print('getattribute a')
      return super().__getattribute__(item)
class B:
    a = A()
    def __getattribute__(self, item):
      if item=='a':
            print('getattribute b')
      return super().__getattribute__(item)

b = B()
print(b.a.x)
'''
getattribute b
get~
getattribute a
666
'''

杨东明 发表于 2021-7-20 16:47:27

class A:
    a = 1

class B:
    c = A()


b = B()
print (b.c.a)

我这么写没有报错。。这两个是一回事吧

逃兵 发表于 2021-7-20 16:53:26

区别在于
这两个魔法方法被改了

    def __get__(self, instance, owner):
      print('get~')
    def __getattribute__(self, item):
      print('getattribute')

kogawananari 发表于 2021-7-20 16:55:43

__get__ 函数你忘了return self

杨东明 发表于 2021-7-20 17:07:56

kogawananari 发表于 2021-7-20 16:55
__get__ 函数你忘了return self

class A:
    x = 666
    def __get__(self, instance, owner):
      print (self,'self')
      print (instance,'instance')
      print (owner,'owner')
      print('get~')
      return self
    def __getattribute__(self, item):
      print('getattribute')
class B:
    a = A()

a = A()
b = B()

#a.x
#print (a,'a')

#print (b,'b')# 通过实例访问属性,都会经过__getattribute__函数。而当该属性不存在时,仍会先访问__getattribute__,但是之后还会接着要访问__getattr__ ,弹出异常。
print (b.a.x ) # 每次访问描述符(descriptor)(即定义了__get__的类),都会先经过__get__函数。
#类方法中定义了__get__就是描述符,从一个类实例访问另一个实例或者它的属性,都会首先触发__get__


我把代码改成这种,结果是:<__main__.A object at 0x000001F6D5753C48> self
<__main__.B object at 0x000001F6D5753D08> instance
<class '__main__.B'> owner
get~
getattribute
None

不知道为啥getattribute被触发了,然后打印了个None??

kogawananari 发表于 2021-7-20 17:15:00

杨东明 发表于 2021-7-20 17:07
我把代码改成这种,结果是: self
instance
owner


描述符是这样的 本来就b.a就想让你返回需要的

你要b.a.x只好改成return self 相当于这不是一个描述符了{:10_292:}

kogawananari 发表于 2021-7-20 17:17:45

kogawananari 发表于 2021-7-20 17:15
描述符是这样的 本来就b.a就想让你返回需要的

你要b.a.x只好改成return self 相当于这不是一个描述符 ...

其实优先级只需要区分描述符和非数据描述符与本体的__getattribute__优先级

也就是说你只需要知道 B.__getattribute__和b.描述符谁优先
而不用知道 b.描述符.__getattribute__和b.描述符.__get__谁优先

kogawananari 发表于 2021-7-20 17:18:34

kogawananari 发表于 2021-7-20 17:17
其实优先级只需要区分描述符和非数据描述符与本体的__getattribute__优先级

也就是说你只需要知道 B._ ...

描述符还分为数据描述符和非数据描述符 优先级也大有区别

杨东明 发表于 2021-7-20 18:44:31

kogawananari 发表于 2021-7-20 17:15
描述符是这样的 本来就b.a就想让你返回需要的

你要b.a.x只好改成return self 相当于这不是一个描述符 ...

我码一下我的疑问噢。。1,描述符不是只要一个类里面定义了__get__就是吗?
2.请问这里如何修改b.a.x不会报错,就是如何改正常?
3.还是没懂这个getattribute为何在加了return self会被触发??

学渣李某人 发表于 2021-7-20 21:20:07

杨东明 发表于 2021-7-20 18:44
我码一下我的疑问噢。。1,描述符不是只要一个类里面定义了__get__就是吗?
2.请问这里如何修改b.a.x不 ...

1. 是的
2. 你的__getattribute__不返回值, 所以print了一个None, 改正常...把get中的语句复制过去, 详见下面的3
3. 任何获取实例属性的行为都会触发__getattribute__, 所以不是return语句触发的, 是b.a.x这句

kogawananari 发表于 2021-7-20 22:34:15

杨东明 发表于 2021-7-20 18:44
我码一下我的疑问噢。。1,描述符不是只要一个类里面定义了__get__就是吗?
2.请问这里如何修改b.a.x不 ...

你问如何修改b.a.x不会报错

写出__set__方法不久可以修改了吗

数据描述符的意思就是 b.a 等价于 普通对象的b.a.x你对b.a重新赋值 就是修改的b.a.x

杨东明 发表于 2021-7-21 15:15:49

kogawananari 发表于 2021-7-20 17:01


请问第五行和第十四行代码print为啥没东西。。?第五行不是返回了一个a吗,十四行是不是返回了a这个实例对象?

杨东明 发表于 2021-7-21 15:18:35

学渣李某人 发表于 2021-7-20 21:20
1. 是的
2. 你的__getattribute__不返回值, 所以print了一个None, 改正常...把get中的语句复制过去, 详 ...

如果把ruturn self去掉的话不会触发getattribute,而是报错,AttributeError: 'NoneType' object has no attribute 'x',我想再问问这个报错是哪里报错?这个报错啥意思?是因为在__get__这儿报错就程序就没有往下执行getattrbute了吗?

qiuyouzhi 发表于 2021-7-21 16:13:49

杨东明 发表于 2021-7-21 15:18
如果把ruturn self去掉的话不会触发getattribute,而是报错,AttributeError: 'NoneType' object has no a ...

b.a.x 相当于访问了两次 __getattribute__
第一次是 b.a,调用了一次,如果没有 return self 就会返回一个 None
后面又要访问 x,如果不返回 self 就是访问 None 的 x 属性,当然会报错

杨东明 发表于 2021-7-21 16:36:49

qiuyouzhi 发表于 2021-7-21 16:13
b.a.x 相当于访问了两次 __getattribute__
第一次是 b.a,调用了一次,如果没有 return self 就会返回一 ...

'第一次是 b.a,调用了一次,如果没有 return self 就会返回一个 None',请问这句中的第一次是指A中的__get__吗?第一句话‘b.a.x 相当于访问了两次 __getattribute__’不知道是不是你说错了,是不是说先访问__get__,再访问__getattribute__。。,我这么理解对么:b.a访问__get__,__get__的返回值会传输到__getattribute__中的self参数,所以这里必须return self?

杨东明 发表于 2021-7-21 16:40:32

qiuyouzhi 发表于 2021-7-21 16:13
b.a.x 相当于访问了两次 __getattribute__
第一次是 b.a,调用了一次,如果没有 return self 就会返回一 ...

class A:
    x = 666
    def __get__(self, instance, owner):
      print('get~')
      return self
    def __getattribute__(self, item):
      print('getattribute a')
      return super().__getattribute__(item)
class B:
    a = A()
    def __getattribute__(self, item):
      if item=='a':
            print('getattribute b')
      return super().__getattribute__(item)

b = B()
print(b.a.x)
'''
getattribute b
get~
getattribute a
666
'''

麻烦再请教一下这个代码为啥return self这一行和B中的return super().__getattribute__(item),print后没打印相应的东西??

qiuyouzhi 发表于 2021-7-21 17:17:04

杨东明 发表于 2021-7-21 16:36
'第一次是 b.a,调用了一次,如果没有 return self 就会返回一个 None',请问这句中的第一次是指A中的__ge ...


通过实例访问属性,都会经过_getattribute__函数。
关 __get__ 什么事,两次都访问的 _getattribute__

杨东明 发表于 2021-7-21 18:42:21

qiuyouzhi 发表于 2021-7-21 17:17


关 __get__ 什么事,两次都访问的 _getattribute__

return self是__get__里面的。。

杨东明 发表于 2021-7-21 18:44:00

qiuyouzhi 发表于 2021-7-21 17:17


关 __get__ 什么事,两次都访问的 _getattribute__

不是访问实例属性才会触发__getattribute__吗?b.a,a不是B的类属性吗?b.a不是访问b的实例属性吗?
页: [1]
查看完整版本: 请问这里b.a.x为啥会报错。。?