属性相关魔法方法不理解
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
【问题】:
看不懂属性相关魔法方法的例子,对上面运行后得到的每一步结果以及上面标记红色的地方不理解,求帮助。 需要返回就有return不需要返回就没有return
本帖最后由 mclb 于 2022-3-14 16:06 编辑
get的方法,你不返还默认返还是None,当你获取对象属性时,__getattribute__魔术方法是第1个进行处理的,也就是说可以做动态加密,__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,__setattr__, __delattr__都是删除或修改对象属性为什么要返还?当然返还一个布尔值也行。 mclb 发表于 2022-3-14 16:04
get的方法,你不返还默认返还是None,当你获取对象属性时,__getattribute__魔术方法是第1个进行处理的,也就是 ...
感谢解答,了解了return的问题
代码中未出现x,它是从何而来? lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题
代码中未出现x,它是从何而来?
随便输的啊,你想输啥都可以 lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题
代码中未出现x,它是从何而来?
__getattr__是最后一个进行处理,意思就是找不到了的时候触发此魔术方法,当你访问一个名叫x属性当然会被触发,我前面不是说过了吗。。。我认为我说的很仔细 lzb1001 发表于 2022-3-14 17:49
感谢解答,了解了return的问题
代码中未出现x,它是从何而来?
当你向对象访问一个属性时,访问属性的顺序是,
调用__getattribute__
调用[数据描述符]
调用当前实例化对象属性
调用当前类(class)属性
调用当前继承父类属性
调用[非数据描述符]
调用__getattr__
当前__getattr__前面几个都没有访问到属性,就是没有找到这个属性此时就会被调用,随便返还什么防止报错。 mclb 发表于 2022-3-14 19:28
当你向对象访问一个属性时,访问属性的顺序是,
调用__getattribute__
调用[数据描述符]
感谢,还有最后一个问题:
>>> c.x
getattribute
1 # 代码中geattribute前面有下划线返回1,无下划线返回getattr?---请帮忙解答下
lzb1001 发表于 2022-3-14 20:49
感谢,还有最后一个问题:
>>> c.x
看不懂你说的啥,但我还是勉强解释一下。如果你认为答非所问,你请你重新描述准确再问我。
因为这个是内置的方法,Python里面一切类型,不管是什么,都会继承object的的方法。
"__getattribute__","__getattr__","__setattr__","__delattr__"之类的方法都是继承object的,你在子类里写了一个"__getattribute__"方法相当于重写了继承的方法,但如果你把前面的下划线删了就不是是继承的了就不会调用了,是你自己重新写的方法跟魔术方法没有任何关系。 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 lzb1001 发表于 2022-3-15 00:43
class C:
def __getattribute__(self, name):
return是返还的意思,print是打印的意思 本帖最后由 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 mclb 发表于 2022-3-15 03:00
不好意思,习惯语法高亮了,没注意到你super用法写错了。把下面的程序里直接复制并分成三份运行一遍, 注 ...
兄弟,他的 super 没写错,你那种是 python2 的写法,
只不过在 python3 也还可以这么用而已 isdkz 发表于 2022-3-15 08:14
兄弟,他的 super 没写错,你那种是 python2 的写法,
只不过在 python3 也还可以这么用而已
super().方法(参数) 默认传入参数我没办法确定是啥, 我习惯写全super(类名,实例).方法(参数)
页:
[1]