【问题标题】:Python class decorator "self" seems wrongPython 类装饰器“self”似乎是错误的
【发布时间】:2018-05-16 06:51:50
【问题描述】:

我正在尝试研究如何使用类上的装饰器更改类的 __setattr__ 的功能,但是在尝试访问替换 __setattr__ 的函数中的 self 时遇到了问题。如果我将问题行更改为不访问self,例如用val = str(val) 替换它,我得到了预期的行为。

我在这里的其他问题中看到了类似的问题,但他们使用了不同的方法,将类用作装饰器。我下面的方法感觉不那么复杂,所以如果可能的话,我很乐意保持这种方式。

为什么a 不能在我期望的self/foo 上定义?

# Define the function to be used as decorator
# The decorator function accepts the relevant fieldname as argument
# and returns the function that wraps the class
def field_proxied(field_name):

    # wrapped accepts the class (type) and modifies the functionality of
    # __setattr__ before returning the modified class (type)
    def wrapped(wrapped_class):
        super_setattr = wrapped_class.__setattr__

        # The new __setattr__ implementation makes sure that given an int,
        # the fieldname becomes a string of that int plus the int in the
        # `a` attribute
        def setattr(self, attrname, val):
            if attrname == field_name and isinstance(val, int):
                val = str(self.a + val)  # <-- Crash. No attribute `a`
                super_setattr(self, attrname, val)
        wrapped_class.__setattr__ = setattr
        return wrapped_class
    return wrapped

@field_proxied("b")
class Foo(object):
    def __init__(self):
        self.a = 2
        self.b = None

foo = Foo()
# <-- At this point, `foo` has no attribute `a`
foo.b = 4
assert foo.b == "6"  # Became a string

【问题讨论】:

    标签: python python-decorators class-decorator


    【解决方案1】:

    问题很简单,改一行就行了。

    def setattr(self, attrname, val):
        if attrname == field_name and isinstance(val, int):
            val = str(self.a + val)
        super_setattr(self, attrname, val)  # changed line
    

    原因是,在你原来的方法中,你只会在attrname == field_name 时调用super_setattr。所以__init__中的self.a = 2根本不像"a" != "b"那样工作。

    【讨论】:

    • 哇哈哈。很棒的收获。你显然是对的。一个简单的缩进错误。我认为我的概念解决方案是可靠的,但错误消息根本没有提供任何帮助。感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 2016-06-13
    • 2013-06-08
    • 1970-01-01
    • 2021-12-23
    • 2012-04-21
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多