我对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。但是,它是我打算实施的代码的大纲。
答案 0 :(得分:5)
简短的回答是否,在完成定义之前,你不能像那样引用你的课程。
类型检查是目前Python开发团队正在积极讨论的一个主题,并且在达成共识的范围内,function annotations是前进的方向:PEP 484描述了方向Guido想要实施它。
该PEP中的前向引用proposed的解决方法是仅使用字符串:
当类型提示包含尚未定义的名称时,该定义可以表示为字符串,稍后要解决。例如,而不是写:
def notify_by_email(employees: Set[Employee]): ...
有人可能写道:
def notify_by_email(employees: 'Set[Employee]'): ...