假设我有一个带有类型注释的函数:
def f(n: float) -> int:
if random.random() >= n:
raise Exception
return 1
我想装饰这个函数,装饰版本将扩展原始函数的返回值:
def decorator(f):
def decorated(max_tries: int, delay: int, *a, **kwa): # annotations?
for i in range(1, max_tries+1):
try:
return True, f(*a, **kwa)
except Exception:
log('try %d of %d failed' % (i, max_tries))
time.sleep(delay)
return False, None
return decorated
在此示例中,我想将原始返回类型int
更改为(bool, Union[int, None])
。
我试过了:
def decorator(f):
@functools.wraps(f)
def decorated(max_tries: int, delay: int, *a, **kwa):
for i in range(1, max_tries+1):
try:
return True, f(*a, **kwa)
except Exception:
log('failed try %d of %d' % (i, max_tries))
time.sleep(delay)
return False, None
ret = f.__annotations__['return']
decorated.__annotations__['return'] = (bool, Union([ret, None]))
return decorated
我得到TypeError: Cannot instantiate <class 'typing.UnionMeta'>
。
有谁知道怎么做?
修改
>>> type(ret)
<class 'typing.UnionMeta'>
>>> isinstance(ret, Union)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python35-32\lib\typing.py", line 563, in __instancecheck__
raise TypeError("Unions cannot be used with isinstance().")
TypeError: Unions cannot be used with isinstance().
输入模块中的类究竟是什么(例如List
,Union
等)?它们在定义函数时是否被实例化?他们为什么不能用手实例化呢?
编辑2:
显然,“实例化”Union
的方法是使用与类型注释中相同的表示法:Union[int, None]
。
def decorator(f):
@functools.wraps(f)
def decorated(max_tries: int, delay: int, *a, **kwa):
for i in range(1, max_tries+1):
try:
return True, f(*a, **kwa)
except Exception:
log('failed try %d of %d' % (i, max_tries))
time.sleep(delay)
return False, None
ret = f.__annotations__['return']
decorated.__annotations__['return'] = (bool, Union[ret, None])
return decorated
现在的问题是将参数max_tries: int
和delay: int
添加到已修饰函数的注释中,并将这些参数添加到help(decorated_f)
中。
对此有何帮助?