gpt4 book ai didi

python - 覆盖 getattr 和 setattr 的方式的根本区别

转载 作者:行者123 更新时间:2023-12-05 08:54:08 25 4
gpt4 key购买 nike

我希望使属性不区分大小写。但是覆盖 __getattr____setattr__ 有点不同,如以下玩具示例所示:

class A(object):

x = 10

def __getattr__(self, attribute):
return getattr(self, attribute.lower())

## following alternatives don't work ##

# def __getattr__(self, attribute):
# return self.__getattr__(attribute.lower())

# def __getattr__(self, attribute):
# return super().__getattr__(attribute.lower())

def __setattr__(self, attribute, value):
return super().__setattr__(attribute.lower(), value)

## following alternative doesn't work ##

# def __setattr__(self, attribute, value):
# return setattr(self, attribute.lower(), value)

a = A()
print(a.x) ## output is 10
a.X = 2
print(a.X) ## output is 2

我对两点感到困惑。

  1. 我假设 getattr()__getattr__ 的语法糖,但它们的行为不同。
  2. 为什么 __setattr__ 需要调用 super(),而 __getattr__ 不需要?

最佳答案

I assume getattr() is a syntactic sugar for __getattr__, but they behave differently.

那是因为假设不正确getattr()经历了整个属性查找过程,其中__getattr__只是一部分。

属性查找首先调用一个不同的 钩子(Hook),即 __getattribute__ method ,默认情况下通过实例字典和类层次结构执行熟悉的搜索。 __getattr__仅当 __getattribute__ 未找到该属性时才会调用.来自 __getattr__ documentation :

Called when the default attribute access fails with an AttributeError (either __getattribute__() raises an AttributeError because name is not an instance attribute or an attribute in the class tree for self; or __get__() of a name property raises AttributeError).

换句话说,__getattr__是一个额外 钩子(Hook),用于访问不存在的属性,否则会引发 AttributeError .

此外,功能如 getattr()len() 不是 dunder 方法的语法糖。他们几乎总是做更多的工作,dunder 方法是一个钩子(Hook),供该进程调用。有时会涉及到多个钩子(Hook),例如这里,或者通过调用类来创建类的实例时。有时连接相当直接,例如 len() ,但即使在简单的情况下,也会进行钩子(Hook)本身不负责的额外检查。

Why does __setattr__ need to call super(), while __getattr__ doesn't?

__getattr__是一个可选 钩子(Hook)。没有默认实现,这就是为什么 super().__getattr__()不起作用。 __setattr__ 不是可选的,所以 object为您提供默认实现。

请注意,通过使用 getattr()你创造了一个无限循环! instance.non_existing会调用__getattribute__('non_existing')然后 __getattr__('non_existing') , 此时您使用 getattr(..., 'non_existing')这叫__getattribute__()然后 __getattr__

在这种情况下,您应该覆盖 __getattribute__相反:

class A(object):
x = 10

def __getattribute__(self, attribute):
return super().__getattribute__(attribute.lower())

def __setattr__(self, attribute, value):
return super().__setattr__(attribute.lower(), value)

关于python - 覆盖 getattr 和 setattr 的方式的根本区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51270662/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com