【问题标题】:Python "__setattr__" and "__getattribute__" confusionPython“__setattr__”和“__getattribute__”混淆
【发布时间】:2019-02-04 16:04:32
【问题描述】:

这段代码有什么问题?

class Spam(object):

    def __init__(self, a, b):
        self.a = a
        self.b = b

    # using this to mark field "c" as deprecated. As per my understanding this gets called only for fields that do not exist.
    def __getattr__(self, c):
        print("Deprecated")

    # using this to manipulate the value before storing
    def __setattr__(self, name, value):
        self.__dict__[name] = value + 1

    # interceptor to allows me to define rules for whenever an attribute's value is accessed
    def __getattribute__(self, name):
        return self.__dict__[name] 

spam = Spam(10, 20)

print(spam.a)
print(spam.b)
print(spam.c)

但是上面的代码没有打印任何东西。这里有什么问题,谁能帮我理解这个?我在https://rszalski.github.io/magicmethods/#access 中读到了这些方法

【问题讨论】:

  • 提示:属性访问self.__dict__是如何解决的?

标签: python python-internals


【解决方案1】:

但是上面的代码没有打印任何东西

错了。它会因无限递归而崩溃。

__getattribute__,当你想记录/拦截呼叫时,在某些时候你仍然想获取原始方法来获取属性。而self.__dict__[name] 调用__getattribute__ 所以这不是正确的做法。

您尝试再次调用此方法并获得无限递归。改为调用父/基方法:

# interceptor to allows me to define rules for whenever an attribute's value is accessed
def __getattribute__(self, name):
    return object.__getattribute__(self,name)  # or super(Spam,self).__getattribute__(name)

打印出来的:

11
21
Deprecated
None

None__getattr__ 返回(因为它只是打印到控制台并隐式返回None)。也许例外是一个更好的主意。

【讨论】:

  • 感谢您的解释。这些神奇的方法调用链有点混乱和违反直觉。
  • 这个设计是透明的,但是你想使用一些高级功能,而且不好用,是的。请记住,object 是所有类之母,因此您可以始终依赖它的方法。
猜你喜欢
  • 2021-05-08
  • 2023-01-23
  • 2011-10-25
  • 1970-01-01
  • 2018-12-24
  • 2010-10-15
  • 2017-12-05
  • 2017-12-15
  • 1970-01-01
相关资源
最近更新 更多