我尝试使用signature()
模块中的inspect
函数,根据我在某些Python函数中提供的类型注释生成一些JavaScript。
当类型是一个简单的内置类时,这部分可以正常工作:
import inspect
def my_function() -> dict:
pass
signature = inspect.signature(my_function)
signature.return_annotation is dict # True
虽然我不确定如何打开和检查更复杂的注释,例如:
from typing import List
import inspect
def my_function() -> List[int]:
pass
signature = inspect.signature(my_function)
signature.return_annotation is List[int] # False
再次引用自定义类的类似问题:
def my_function() -> List['User']:
pass
...
signature.return_annotation # typing.List[_ForwardRef('User')]
我想要离开的是这样的 - 所以我可以在生成JavaScript时适当地分支:
type = signature.return_annotation... # list
member_type = signature.return_annotation... # int / 'User'
感谢。
答案 0 :(得分:2)
List
不是GenericMeta
类型的地图,尽管有语法。每次访问都会生成一个新实例:
>>> [ id(List[str]) for i in range(3) ]
[33105112, 33106872, 33046936]
这意味着即使List[int] is not List[int]
。要比较两个实例,您有多个选项:
==
,即signature.return_annotation == List[int]
。将您的类型的实例存储在全局变量中,然后检查它,即
a = List[int]
def foo() -> a:
pass
inspect.signature(foo).return_annotation is a
使用issubclass
。打字模块定义了。请注意,这可能比您更喜欢,请务必阅读_TypeAlias
文档。
List
并自行阅读内容。虽然属性是内部的,但实现不太可能很快改变:List[int].__args__[0]
包含从Python 3.5.2开始的类型参数,在早期版本中包含List[int].__parameters__[0]
。如果您想为导出器编写通用代码,那么最后一个选项可能是最佳选择。如果您只需要涵盖特定用例,我个人可以使用==
。
答案 1 :(得分:2)
对于Python 3.5.2,请看一下phillip的答案。
您不应该像Phillip所说的那样使用身份运营商进行检查,使用相等来做到这一点。
要检查提示是否是list
的子类,您可以使用issubclass
检查(即使您应该注意在某些情况下这可能是古怪的并且目前正在处理):< / p>
issubclass(List[int], list) # True
要获得类型提示的成员,您通常需要注意所涉及的案例。
如果它有一个简单类型,就像在List[int]
中一样,参数的值位于__parameters__
值中:
signature.return_annotation.__parameters__[0] # int
现在,在更复杂的场景中,即作为List[User]
的参数提供的类,您必须再次提取__parameter__[0]
,然后获取__forward_arg__
。这是因为Python将参数包装在一个特殊的ForwardRef
类中:
d = signature.return_annotation.__parameter__[0]
d.__forward_arg__ # 'User'
记下,这里不需要实际使用inspect
,typing
有一个名为get_type_hints
的辅助函数,它返回类型提示为字典(它使用函数对象__annotations__
属性)。
答案 2 :(得分:0)
Python 3.8为此提供了typing.get_origin()
和typing.get_args()
!
assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)
assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)
请参见https://docs.python.org/3/library/typing.html#typing.get_origin