允许 python 装饰器在被传递的 class 内部使用时将 class 作为参数

Allowing a python decorator to take a class as a parameter when used inside the class being passed

我在使用 Python 装饰器时遇到了一些困难,我认为这与我将 class 作为参数传递给函数装饰器有关,当函数被decorated 是传递 class 的一种方法。

我没有比这更清楚的问题解释了,所以希望一些代码能有所帮助:

from typeChecking import *

class Vector:
    @accepts(Vector, float, float, float) #Vector hasn't been defined yet... In c++ I could forward declare...
    def __init__(self, x, y, z):
        self._x = float(x)
        self._y = float(y)
        self._z = float(z)
    ...

我认为 @accepts 的定义不重要,但为了以防万一,我还是把它留在这里:

def accepts(*types):
    def check_accepts(f):
        assert len(types) == f.func_code.co_argcount
        def new_f(*args, **kwds):
            for (a, t) in zip(args, types):
                assert isinstance(a, t), \
                       "arg %r does not match %s" % (a,t)
            return f(*args, **kwds)
        new_f.func_name = f.func_name
        return new_f
    return check_accepts

我收到以下错误:

File "raytracerBase.py", line 41, in <module>
  class Vector:
File "raytracerBase.py", line 42, in Vector
  @accepts(Vector, float, float, float)
NameError: name 'Vector' is not defined

我认为我的评论解释了我认为正在发生的事情:class 尚未定义(因为,​​我正在定义它),因此我不能通过它。

是否有一个巧妙的解决方法不是:

assert isinstance(self, Vector), "Something is wrong... very wrong..."

我知道我进行的类型检查超出了必要的范围,但我还是想知道如何解决此类问题。

编辑: 我也知道 @accepts 实际上无效 Python。但是,这是我打算实现的代码大纲。

简短的回答是,在完成定义之前,您不能那样引用您的class。

类型检查是 Python 开发团队目前正在积极讨论的主题,就达成共识而言,function annotations are the way forward: PEP 484 描述了 Guido 想要采取的方向在实施中。

该 PEP 中前向引用 proposed 的解决方法是仅使用字符串代替:

When a type hint contains names that have not been defined yet, that definition may be expressed as a string, to be resolved later. For example, instead of writing:

def notify_by_email(employees: Set[Employee]): ...

one might write:

def notify_by_email(employees: 'Set[Employee]'): ...