英文:
How can I write a python decorator for a input function with type hinting?
问题
I'm trying to create the following python decorator for a function with type hint but it doesn't seem to work. It returned None instead of True. What did I do wrong?
def do_nothing(func):
def Inner_Function(*args, **kwargs):
func(*args, **kwargs)
return Inner_Function
@do_nothing
def is_cold(name: str) -> bool:
return True
g = is_cold("hi")
print(g)
# >> None
英文:
I'm trying create the following python decorator for a function with type hint but it doesn't seem to work. It returned None instead of True. What did I do wrong?
def do_nothing(func):
def Inner_Function(*args, **kwargs):
func(*args, **kwargs)
return Inner_Function
@do_nothing
def is_cold(name: str) -> bool:
return True
g = is_cold("hi")
print(g)
>> None
答案1
得分: 1
要修复你的装饰器的实际运行行为,内部函数需要return
原始函数的调用结果:
def do_nothing(func):
def Inner_Function(*args, **kwargs):
return func(*args, **kwargs)
return Inner_Function
@do_nothing
def is_cold(name: str) -> bool:
return True
g = is_cold("hi")
print(g) # True
如果你正在使用类型检查,你会注意到这个装饰器会破坏被装饰函数的类型。如果我们在mypy
中检查g
的类型,我们会看到它是Any
:
g = is_cold("hi")
reveal_type(g) # Revealed type is "Any"
为了解决这个问题,你需要为你的装饰器添加类型提示,以指示它接受一个函数作为参数,并返回相同类型的函数:
from typing import Callable, TypeVar
_Func = TypeVar("_Func", bound=Callable)
def do_nothing(func: _Func) -> _Func:
def Inner_Function(*args, **kwargs):
return func(*args, **kwargs)
return Inner_Function # type: ignore
(你可以为Inner_Function
做更复杂的类型提示,以消除# type: ignore
的需要,但就@do_nothing
装饰器的用户而言,内部发生的事情并不重要,只有do_nothing
本身的签名才重要。)
现在is_cold
的类型由装饰器保留:
g = is_cold("hi")
reveal_type(g) # Revealed type is "builtins.bool"
英文:
To fix the actual runtime behavior of your decorator, the inner function needs to return
the result of calling the original function:
def do_nothing(func):
def Inner_Function(*args, **kwargs):
return func(*args, **kwargs)
return Inner_Function
@do_nothing
def is_cold(name: str) -> bool:
return True
g = is_cold("hi")
print(g) # True
If you're using typechecking, you'll notice that this decorator breaks the typing of the decorated function. If we check the type of g
in mypy
we'll see that it's Any
:
g = is_cold("hi")
reveal_type(g) # Revealed type is "Any"
To fix this, you need to add typing to your decorator to indicate that it takes a function as its argument and returns the same type of function:
from typing import Callable, TypeVar
_Func = TypeVar("_Func", bound=Callable)
def do_nothing(func: _Func) -> _Func:
def Inner_Function(*args, **kwargs):
return func(*args, **kwargs)
return Inner_Function # type: ignore
(You can do more complex typing for Inner_Function
to eliminate the need for the # type: ignore
, but as far as the users of the @do_nothing
decorator are concerned, what happens inside doesn't matter, only the signature of do_nothing
itself.)
Now is_cold
has its type preserved by the decorator:
g = is_cold("hi")
reveal_type(g) # Revealed type is "builtins.bool"
答案2
得分: 0
InnerFunction
调用 func
但没有返回任何内容。 is_cold
将返回 True
,但然后 InnerFunction
将其丢弃,并默认返回 None
。
英文:
InnerFunction
calls func
but doesn't return
anything. is_cold
will return True
, but then InnerFunction
tosses that away and, by default, returns None
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论