【问题标题】:Accessing static fields from the decorated class从装饰类访问静态字段
【发布时间】:2017-12-19 16:56:49
【问题描述】:

完整代码示例:

def decorator(class_):
    class Wrapper:
        def __init__(self, *args, **kwargs):
            self.instance = class_(*args, **kwargs)

        @classmethod
        def __getattr__(cls, attr):
            return getattr(class_, attr)
    return Wrapper


@decorator
class ClassTest:

    static_var = "some value"


class TestSomething:

    def test_decorator(self):
        print(ClassTest.static_var)
        assert True

尝试执行测试时,出现错误:

test/test_Framework.py F
test/test_Framework.py:37 (TestSomething.test_decorator)
self = <test_Framework.TestSomething object at 0x10ce3ceb8>

    def test_decorator(self):
>       print(ClassTest.static_var)
E       AttributeError: type object 'Wrapper' has no attribute 'static_var'

是否可以从装饰类访问静态字段?

【问题讨论】:

  • 你能显示你得到错误的代码吗?从上面的代码 sn-ps 并不能立即看出问题所在。
  • 如果您在单个 sn-p 中提供了导致错误的所有代码,将会很有帮助。我花了几分钟才明白你在做什么。
  • edit您的问题而不是发表评论,以便您可以正确格式化代码。
  • 已发布完整代码。
  • TestSomething 类对于这个问题不是必需的,所以我删除了它。

标签: python class class-decorator


【解决方案1】:

虽然@martineau 的答案可能更好地解决了您要解决的特定问题,但更通用的方法可能是使用创建元类来重新定义 instance 方法 __getattr__ on一个type 实例(类是type 的实例)。

def decorator(class_):
    class WrapperMeta(type):
        def __getattr__(self, attr):
            return getattr(class_, attr)

    class Wrapper(metaclass=WrapperMeta):
        def __init__(self, *args, **kwargs):
            self.instance = class_(*args, **kwargs)

    return Wrapper

这允许对类本身的属性查找通过WrapperMeta.__getattr__ 传递。

【讨论】:

  • @Oleh Kuzovkov:IMO 这个答案比我的好——所以你应该接受它。 Jared:元有趣!
  • 这个问题的主要目的是绕过对装饰类的字段调用。继承肯定解决了这个问题,但是这个解决方案确实更适合这种情况。谢谢你们!
【解决方案2】:

你可以通过让装饰器创建一个从被装饰的类派生的类来让它工作。

这就是我的意思:

def decorator(class_):
    class Wrapper(class_):
        def __init__(self, *args, **kwargs):
            self.instance = super().__init__(*args, **kwargs)

    return Wrapper

@decorator
class ClassTest:
    static_var = "some value"

print(ClassTest.static_var)  # -> some value

【讨论】:

  • 你能解释一下为什么原始代码不起作用吗?作为一个python新手,我对__getattr__()方法不熟悉。为什么它不像 OP 期望的那样工作?
  • 一个类没有这个方法__getattr__(),仅此而已。您可以改用getattr(class_, name),我认为这很有效。
  • @Code-Apprentice:因为 OP 代码中定义的 __getattr__()Wrapper 类方法。你可以通过在线阅读documentation了解更多关于__getattr__()的信息。
  • @martineau - 为了避免从 class_ 继承 - 可以使用元类来覆盖 Wrapper getattr(一些 MetaWrapper)吗?
  • 修饰后,名称ClassTest指的是类Wrapper,对吗?那么Classtest.static_var 不应该在Wrapper 中调用__getattr__() 吗?
猜你喜欢
  • 2018-01-02
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多