鱼C论坛

 找回密码
 立即注册
查看: 1783|回复: 13

属性相关魔法方法不理解

[复制链接]
发表于 2022-3-14 14:32:42 | 显示全部楼层 |阅读模式

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

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

x
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

【问题】:

看不懂属性相关魔法方法的例子,对上面运行后得到的每一步结果以及上面标记红色的地方不理解,求帮助。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-14 14:38:25 From FishC Mobile | 显示全部楼层
需要返回就有return不需要返回就没有return
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-14 16:04:28 From FishC Mobile | 显示全部楼层
本帖最后由 mclb 于 2022-3-14 16:06 编辑

get的方法,你不返还默认返还是None,当你获取对象属性时,__getattribute__魔术方法是第1个进行处理的,也就是说可以做动态加密,__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,__setattr__, __delattr__都是删除或修改对象属性为什么要返还?当然返还一个布尔值也行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

代码中未出现x,它是从何而来?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-14 17:59:57 From FishC Mobile | 显示全部楼层
lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

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

随便输的啊,你想输啥都可以
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-14 19:15:31 From FishC Mobile | 显示全部楼层
lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

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

__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,当你访问一个名叫x属性当然会被触发,我前面不是说过了吗。。。我认为我说的很仔细
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-14 19:28:27 From FishC Mobile | 显示全部楼层
lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题

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

当你向对象访问一个属性时,访问属性的顺序是,
    调用__getattribute__
    调用[数据描述符]
    调用当前实例化对象属性
    调用当前类(class)属性
    调用当前继承父类属性
    调用[非数据描述符]
    调用__getattr__
当前__getattr__前面几个都没有访问到属性,就是没有找到这个属性此时就会被调用,随便返还什么防止报错。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-14 20:49:58 | 显示全部楼层
mclb 发表于 2022-3-14 19:28
当你向对象访问一个属性时,访问属性的顺序是,
    调用__getattribute__
    调用[数据描述符]

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

>>> c.x
getattribute
1                  # 代码中geattribute前面有下划线返回1,无下划线返回getattr?---请帮忙解答下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-14 21:48:27 From FishC Mobile | 显示全部楼层
lzb1001 发表于 2022-3-14 20:49
感谢,还有最后一个问题:

>>> c.x

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

使用道具 举报

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

使用道具 举报

发表于 2022-3-15 01:56:24 From FishC Mobile | 显示全部楼层
lzb1001 发表于 2022-3-15 00:43
class C:

    def __getattribute__(self, name):

return是返还的意思,print是打印的意思
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-15 03:00:16 From FishC Mobile | 显示全部楼层
本帖最后由 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 [item]  # 返回 [属性名]


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

使用道具 举报

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

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

只不过在 python3 也还可以这么用而已
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-15 12:09:41 From FishC Mobile | 显示全部楼层
isdkz 发表于 2022-3-15 08:14
兄弟,他的 super 没写错,你那种是 python2 的写法,

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

super().方法(参数) 默认传入参数我没办法确定是啥, 我习惯写全super(类名,实例).方法(参数)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-12 00:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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