没有获得此信息的官方方法。该
typing模块仍在大量开发中,并且没有公共API可言。(实际上,它可能永远不会有一个。)
我们所能做的就是查看模块的内部结构,并找到最简捷的方式来获取我们所需要的信息。而且由于该模块仍在开发中,其内部结构将发生变化。很多。
在python
3.5和3.6,泛型有一个
__origin__是保持的参照原来的通用基类(即属性
List[int].__origin__会一直
List),但是这是在3.7改变。现在,找出某物是否通用的最简单方法可能是检查其
__parameters__和
__args__属性。
这是一组可用于检测泛型的函数:
import typingif hasattr(typing, '_GenericAlias'): # python 3.7 def _is_generic(cls): if isinstance(cls, typing._GenericAlias): return True if isinstance(cls, typing._SpecialForm): return cls not in {typing.Any} return False def _is_base_generic(cls): if isinstance(cls, typing._GenericAlias): if cls.__origin__ in {typing.Generic, typing._Protocol}: return False if isinstance(cls, typing._VariadicGenericAlias): return True return len(cls.__parameters__) > 0 if isinstance(cls, typing._SpecialForm): return cls._name in {'ClassVar', 'Union', 'Optional'} return Falseelse: # python <3.7 if hasattr(typing, '_Union'): # python 3.6 def _is_generic(cls): if isinstance(cls, (typing.Genericmeta, typing._Union, typing._Optional, typing._ClassVar)): return True return False def _is_base_generic(cls): if isinstance(cls, (typing.Genericmeta, typing._Union)): return cls.__args__ in {None, ()} if isinstance(cls, typing._Optional): return True return False else: # python 3.5 def _is_generic(cls): if isinstance(cls, (typing.Genericmeta, typing.Unionmeta, typing.Optionalmeta, typing.Callablemeta, typing.Tuplemeta)): return True return False def _is_base_generic(cls): if isinstance(cls, typing.Genericmeta): return all(isinstance(arg, typing.TypeVar) for arg in cls.__parameters__) if isinstance(cls, typing.Unionmeta): return cls.__union_params__ is None if isinstance(cls, typing.Tuplemeta): return cls.__tuple_params__ is None if isinstance(cls, typing.Callablemeta): return cls.__args__ is None if isinstance(cls, typing.Optionalmeta): return True return Falsedef is_generic(cls): """ Detects any kind of generic, for example `List` or `List[int]`. This includes "special" types like Union and Tuple - anything that's subscriptable, basically. """ return _is_generic(cls)def is_base_generic(cls): """ Detects generic base classes, for example `List` (but not `List[int]`) """ return _is_base_generic(cls)def is_qualified_generic(cls): """ Detects generics with arguments, for example `List[int]` (but not `List`) """ return is_generic(cls) and not is_base_generic(cls)
所有这些功能均应在所有<= 3.7的python版本中起作用(包括使用
typing模块反向移植的所有<3.5版本)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)