鱼C论坛

 找回密码
 立即注册
查看: 2341|回复: 19

[已解决]请问这里b.a.x为啥会报错。。?

[复制链接]
发表于 2021-7-20 16:45:58 | 显示全部楼层 |阅读模式
8鱼币
  1. class A:
  2.     x = 666
  3.     def __get__(self, instance, owner):
  4.         print('get~')
  5.     def __getattribute__(self, item):
  6.         print('getattribute')
  7. class B:
  8.     a = A()

  9. a = A()
  10. b = B()

  11. a.x  # 通过实例访问属性,都会经过__getattribute__函数。而当该属性不存在时,仍会先访问__getattribute__,但是之后还会接着要访问__getattr__ ,弹出异常。
  12. b.a.x  # 每次访问描述符(descriptor)(即定义了__get__的类),都会先经过__get__函数。
复制代码
最佳答案
2021-7-20 16:45:59
  1. class A:
  2.     x = 666
  3.     def __get__(self, instance, owner):
  4.         print('get~')
  5.         return self
  6.     def __getattribute__(self, item):
  7.         print('getattribute a')
  8.         return super().__getattribute__(item)
  9. class B:
  10.     a = A()
  11.     def __getattribute__(self, item):
  12.         if item=='a':
  13.             print('getattribute b')
  14.         return super().__getattribute__(item)

  15. b = B()
  16. print(b.a.x)
  17. '''
  18. getattribute b
  19. get~
  20. getattribute a
  21. 666
  22. '''
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-20 16:45:59 | 显示全部楼层    本楼为最佳答案   
  1. class A:
  2.     x = 666
  3.     def __get__(self, instance, owner):
  4.         print('get~')
  5.         return self
  6.     def __getattribute__(self, item):
  7.         print('getattribute a')
  8.         return super().__getattribute__(item)
  9. class B:
  10.     a = A()
  11.     def __getattribute__(self, item):
  12.         if item=='a':
  13.             print('getattribute b')
  14.         return super().__getattribute__(item)

  15. b = B()
  16. print(b.a.x)
  17. '''
  18. getattribute b
  19. get~
  20. getattribute a
  21. 666
  22. '''
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-20 16:47:27 | 显示全部楼层
class A:
    a = 1

class B:
    c = A()


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

我这么写没有报错。。这两个是一回事吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-20 16:53:26 | 显示全部楼层
区别在于
这两个魔法方法被改了

  1.     def __get__(self, instance, owner):
  2.         print('get~')
  3.     def __getattribute__(self, item):
  4.         print('getattribute')
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-20 16:55:43 | 显示全部楼层
__get__ 函数你忘了return self
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-20 17:07:56 | 显示全部楼层
kogawananari 发表于 2021-7-20 16:55
__get__ 函数你忘了return self
  1. class A:
  2.     x = 666
  3.     def __get__(self, instance, owner):
  4.         print (self,'self')
  5.         print (instance,'instance')
  6.         print (owner,'owner')
  7.         print('get~')
  8.         return self
  9.     def __getattribute__(self, item):
  10.         print('getattribute')
  11. class B:
  12.     a = A()

  13. a = A()
  14. b = B()

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

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



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

不知道为啥getattribute被触发了,然后打印了个None??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-20 17:15:00 | 显示全部楼层
杨东明 发表于 2021-7-20 17:07
我把代码改成这种,结果是: self
instance
owner

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

你要b.a.x只好改成return self 相当于这不是一个描述符了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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__谁优先
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-20 17:18:34 | 显示全部楼层
kogawananari 发表于 2021-7-20 17:17
其实优先级只需要区分描述符和非数据描述符与本体的__getattribute__优先级

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

描述符还分为数据描述符和非数据描述符 优先级也大有区别
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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会被触发??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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这句
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-21 15:15:49 | 显示全部楼层

请问第五行和第十四行代码print为啥没东西。。?第五行不是返回了一个a吗,十四行是不是返回了a这个实例对象?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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 属性,当然会报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-21 16:40:32 | 显示全部楼层
qiuyouzhi 发表于 2021-7-21 16:13
b.a.x 相当于访问了两次 __getattribute__
第一次是 b.a,调用了一次,如果没有 return self 就会返回一 ...
  1. class A:
  2.     x = 666
  3.     def __get__(self, instance, owner):
  4.         print('get~')
  5.         return self
  6.     def __getattribute__(self, item):
  7.         print('getattribute a')
  8.         return super().__getattribute__(item)
  9. class B:
  10.     a = A()
  11.     def __getattribute__(self, item):
  12.         if item=='a':
  13.             print('getattribute b')
  14.         return super().__getattribute__(item)

  15. b = B()
  16. print(b.a.x)
  17. '''
  18. getattribute b
  19. get~
  20. getattribute a
  21. 666
  22. '''
复制代码


麻烦再请教一下这个代码为啥return self这一行和B中的return super().__getattribute__(item),print后没打印相应的东西??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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


通过实例访问属性,都会经过_getattribute__函数。

关 __get__ 什么事,两次都访问的 _getattribute__
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-21 18:42:21 | 显示全部楼层
qiuyouzhi 发表于 2021-7-21 17:17


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

return self是__get__里面的。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-21 18:44:00 | 显示全部楼层
qiuyouzhi 发表于 2021-7-21 17:17


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

不是访问实例属性才会触发__getattribute__吗?b.a,a不是B的类属性吗?b.a不是访问b的实例属性吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-19 11:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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