允许python装饰器在传递的类中使用时将类作为参数

时间:2015-02-08 20:06:40

标签: python typechecking python-decorators

我对Python装饰器有一些困难,我认为这与我将一个类作为参数传递给函数装饰器的事实有关,当被装饰的函数是类的一个方法时过去了。

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

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

我认为我的评论解释了我的想法:课程还没有被定义(因为,​​我正在定义它),因此我无法通过它。

是否有一个简洁的解决方法:

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

我知道我的检查超出了认为必要的范围,但我想知道如何解决这类问题。

编辑:我也知道@accepts实际上并不是有效的Python。但是,它是我打算实施的代码的大纲。

1 个答案:

答案 0 :(得分:5)

简短的回答是,在完成定义之前,你不能像那样引用你的课程。

类型检查是目前Python开发团队正在积极讨论的一个主题,并且在达成共识的范围内,function annotations是前进的方向:PEP 484描述了方向Guido想要实施它。

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

  

当类型提示包含尚未定义的名称时,该定义可以表示为字符串,稍后要解决。例如,而不是写:

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

有人可能写道:

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