lzb1001 发表于 2022-3-14 14:32:42

属性相关魔法方法不理解

class C:

    def __getattribute__(self, name):
      print('getattribute')
      return super().__getattribute__(name) # 使用super()调用object基类的__getattribute__()方法。 # 为何此处有return?

    def __getattr__(self, name):
      print('getattr')

    def __setattr__(self, name, value):
      print('setattr')
      super().__setattr__(name, value) # 为何无return?

    def __delattr__(self, name):
      print('delattr')
      super().__delattr__(name) # 为何无return?

运行后:

>>> c = C()

>>> c.x # 代码中未出现x,它是从何而来?
getattribute
getattr

>>> c.x = 1
setattr

>>> c.x
getattribute
1 # 代码中geattribute前面有下划线返回1,无下划线返回getattr?

>>> del c.x
delattr

>>> setattr(c, 'y', 'Yellow')
setattr

【问题】:

看不懂属性相关魔法方法的例子,对上面运行后得到的每一步结果以及上面标记红色的地方不理解,求帮助。

wp231957 发表于 2022-3-14 14:38:25

需要返回就有return不需要返回就没有return

mclb 发表于 2022-3-14 16:04:28

本帖最后由 mclb 于 2022-3-14 16:06 编辑

get的方法,你不返还默认返还是None,当你获取对象属性时,__getattribute__魔术方法是第1个进行处理的,也就是说可以做动态加密,__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,__setattr__, __delattr__都是删除或修改对象属性为什么要返还?当然返还一个布尔值也行。

lzb1001 发表于 2022-3-14 17:49:39

mclb 发表于 2022-3-14 16:04
get的方法,你不返还默认返还是None,当你获取对象属性时,__getattribute__魔术方法是第1个进行处理的,也就是 ...

感谢解答,了解了return的问题

代码中未出现x,它是从何而来?

wp231957 发表于 2022-3-14 17:59:57

lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

代码中未出现x,它是从何而来?

随便输的啊,你想输啥都可以

mclb 发表于 2022-3-14 19:15:31

lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

代码中未出现x,它是从何而来?

__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,当你访问一个名叫x属性当然会被触发,我前面不是说过了吗。。。我认为我说的很仔细

mclb 发表于 2022-3-14 19:28:27

lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

代码中未出现x,它是从何而来?

当你向对象访问一个属性时,访问属性的顺序是,
    调用__getattribute__
    调用[数据描述符]
    调用当前实例化对象属性
    调用当前类(class)属性
    调用当前继承父类属性
    调用[非数据描述符]
    调用__getattr__
当前__getattr__前面几个都没有访问到属性,就是没有找到这个属性此时就会被调用,随便返还什么防止报错。

lzb1001 发表于 2022-3-14 20:49:58

mclb 发表于 2022-3-14 19:28
当你向对象访问一个属性时,访问属性的顺序是,
    调用__getattribute__
    调用[数据描述符]


感谢,还有最后一个问题:

>>> c.x
getattribute
1                  # 代码中geattribute前面有下划线返回1,无下划线返回getattr?---请帮忙解答下

mclb 发表于 2022-3-14 21:48:27

lzb1001 发表于 2022-3-14 20:49
感谢,还有最后一个问题:

>>> c.x


看不懂你说的啥,但我还是勉强解释一下。如果你认为答非所问,你请你重新描述准确再问我。
因为这个是内置的方法,Python里面一切类型,不管是什么,都会继承object的的方法。
"__getattribute__","__getattr__","__setattr__","__delattr__"之类的方法都是继承object的,你在子类里写了一个"__getattribute__"方法相当于重写了继承的方法,但如果你把前面的下划线删了就不是是继承的了就不会调用了,是你自己重新写的方法跟魔术方法没有任何关系。

lzb1001 发表于 2022-3-15 00:43:35

mclb 发表于 2022-3-14 21:48
看不懂你说的啥,但我还是勉强解释一下。如果你认为答非所问,你请你重新描述准确再问我。
因为这个是内 ...

class C:

    def __getattribute__(self, name):
      print('getattribute')
      return super().__getattribute__(name) # 此行代码返回结果?

    def __getattr__(self, name):
      print('getattr')

    def __setattr__(self, name, value):
      print('setattr')
      super().__setattr__(name, value) # 此行代码返回结果?

    def __delattr__(self, name):
      print('delattr')
      super().__delattr__(name) # 此行代码返回结果?

运行后:

>>> c = C()

>>> c.x
getattribute
getattr # 哪行代码返回的结果?

>>> c.x = 1
setattr

>>> c.x
getattribute
1 # 哪行代码返回的结果?

>>> del c.x
delattr

>>> setattr(c, 'y', 'Yellow')
setattr

mclb 发表于 2022-3-15 01:56:24

lzb1001 发表于 2022-3-15 00:43
class C:

    def __getattribute__(self, name):


return是返还的意思,print是打印的意思

mclb 发表于 2022-3-15 03:00:16

本帖最后由 mclb 于 2022-3-15 10:07 编辑

lzb1001 发表于 2022-3-15 00:43
class C:

    def __getattribute__(self, name):


不好意思,习惯语法高亮了,没注意到你super用法写错了。把下面的程序里直接复制并分成三份运行一遍, 注释都写了,你应该懂的。

# coding=utf-8

class Demo0(object):
    def __getattribute__(self, item):
      value = object.__getattribute__(self, item)# 通过父类object的__getattribute__方法获取当前实例化对象的属性
      # value = super(Demo0, self).__getattribute__(item)#效果与上一行一样,只有这两种写法才可以使用父类访问当前对象属性,而不会触发魔法
      print(item, value)# 打印 (属性名, 属性值)
      return value# 返回 属性值

    def __getattr__(self, item):
      return # 返回 [属性名]


Test0 = Demo0()
value = Test0.a
print(value)


class Demo1(object):
    def __getattribute__(self, item):
      value = object.__getattribute__(self, item)# 通过父类object的__getattribute__方法获取当前实例化对象的属性
      # value = super(Demo1, self).__getattribute__(item)#效果与上一行一样
      print(item, value)# 打印 (属性名, 属性值)
      return value# 返回 属性值

    def __getattr__(self, item):
      print("找不到名为 %s 的属性" % item)# 打印 (找不到的属性名)


Test1 = Demo1()
Test1.b


class Demo2(object):
    def __getattribute__(self, item):
      value = object.__getattribute__(self, item)# 通过父类object的__getattribute__方法获取当前实例化对象的属性
      # value = super(Demo2, self).__getattribute__(item)#效果与上一行一样
      print(item, value)# 打印 (属性名, 属性值)
      return value# 返回 属性值


Test2 = Demo2()
Test2.c

isdkz 发表于 2022-3-15 08:14:50

mclb 发表于 2022-3-15 03:00
不好意思,习惯语法高亮了,没注意到你super用法写错了。把下面的程序里直接复制并分成三份运行一遍, 注 ...

兄弟,他的 super 没写错,你那种是 python2 的写法,

只不过在 python3 也还可以这么用而已

mclb 发表于 2022-3-15 12:09:41

isdkz 发表于 2022-3-15 08:14
兄弟,他的 super 没写错,你那种是 python2 的写法,

只不过在 python3 也还可以这么用而已

super().方法(参数) 默认传入参数我没办法确定是啥, 我习惯写全super(类名,实例).方法(参数)
页: [1]
查看完整版本: 属性相关魔法方法不理解