【问题标题】:Decorator on class makes class NoneType when importing类上的装饰器在导入时使类 NoneType
【发布时间】:2023-04-04 13:42:02
【问题描述】:

我试图理解为什么我的类上的装饰器在尝试从另一个脚本导入类时会以这种方式修改类,使其看起来是“NoneType”。

my_class.py 我有:

my_dict = dict()

def register(cls):
    name = cls.__name__
    my_dict[name] = cls

@register  # will be commented
class MyClass:
    def my_method(self):
        print("running class method")

print("my_dict: ", my_dict)

在另一个模块中 my_main.py 我导入了类似的类

from my_class import MyClass

print(type(MyClass))
print(MyClass.my_method)

如果我使用$ python3 my_main.py 运行它,我会得到以下输出:

my_dict:  {'MyClass': <class 'my_class.MyClass'>}
<class 'NoneType'>
Traceback (most recent call last):
  File "my_main.py", line 4, in <module>
    print(MyClass.my_method)
AttributeError: 'NoneType' object has no attribute 'my_method'

通过注释my_class.py 中的@register 行,my_main.py 运行时不会出现错误并输出:

my_dict:  {}
<class 'type'>
<function MyClass.my_method at 0x7ff06f254f28>

..但显然 my_dict 不再填充。有没有办法用给定的装饰器注册my_class 并在将它导入另一个脚本后访问类的属性?

【问题讨论】:

  • 你的装饰器不会返回你的类(但 None 隐含)。在您的注册功能中添加return cls
  • 哦,当然……现在说得通了——非常感谢!

标签: python class import decorator python-decorators


【解决方案1】:

装饰器不仅仅是一个普通的函数。

我不想过多描述如何正确编写装饰器。但至少,你应该让你的装饰器返回一个class

当你为一个函数编写一个装饰器时也是如此。装饰器至少应该返回一个函数。

例如:

def decorator(method):
    @functools.wraps(method)
    def wrapper(*args, **kwargs):
        print("Hi")
        return method(*args, **kwargs)
    return wrapper

当你使用这个装饰器装饰一个函数时,你实际上是将该函数传递给装饰器:new_function = decorator(original_function)

这意味着new_functionwrapper 包裹。这就是装饰器的工作原理。当你执行修饰函数时,它实际上执行的是wrapper:

print("Hi")
return method(*args, **kwargs)  # pass all args to original function and return its return value.

在您的代码中,您的装饰器只返回 None

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 2019-03-25
    • 2014-01-14
    • 2011-09-17
    • 2021-07-16
    • 1970-01-01
    • 2021-01-23
    相关资源
    最近更新 更多