我正在尝试编写验证类型提示的代码,为了做到这一点,我必须找出注释是什么类型的对象.例如,考虑一下该片段应该告诉用户期望的值是什么类型:
import typing
typ = typing.Union[int, str]
if issubclass(typ, typing.Union):
print('value type should be one of', typ.__args__)
elif issubclass(typ, typing.Generic):
print('value type should be a structure of', typ.__args__[0])
else:
print('value type should be', typ)
Run Code Online (Sandbox Code Playgroud)
这应该打印"值类型应该是(int,str)之一",而是抛出异常:
Traceback (most recent call last):
File "untitled.py", line 6, in <module>
if issubclass(typ, typing.Union):
File "C:\Python34\lib\site-packages\typing.py", line 829, in __subclasscheck__
raise TypeError("Unions cannot be used with issubclass().")
TypeError: Unions cannot be used with issubclass().
Run Code Online (Sandbox Code Playgroud)
isinstance 也不起作用:
>>> isinstance(typ, typing.Union)
Traceback (most recent call last):
File …Run Code Online (Sandbox Code Playgroud) 假设您有一个继承自 Generic[T] 的 Python 类。有没有办法获得从类/实例中传入的实际类型?
例如,
from typing import TypeVar, Type
T = TypeVar('T')
class Test(Generic[T]):
def hello(self):
my_type = T # this is wrong!
print( "I am {0}".format(my_type) )
Test[int]().hello() # should print "I am int"
Run Code Online (Sandbox Code Playgroud)
在这里,建议类型 arg 出现在类型的 args 字段中。而且确实,
print( str( Test[int].__args__ ) )
Run Code Online (Sandbox Code Playgroud)
将打印 (<class 'int'>,)。但是,我似乎无法直接从实例中访问它,例如替换
my_type = self.__class__.__args__ # this is also wrong (None)
Run Code Online (Sandbox Code Playgroud)
似乎没有诀窍。
谢谢
typing除了类型提示以外,我在使用Python中的类型时遇到了一些问题:
>>> from typing import List
>>> string_list = ['nobody', 'expects', 'the', 'spanish', 'inqusition']
>>> string_list_class = List[str]
Run Code Online (Sandbox Code Playgroud)
现在我想
string_list符合string_list_class。string_list_class为列表。string_list_class是一个列表。我发现自己无法实现以下任何一个目标:
>>> isinstance(string_list, string_list_class)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 708, in __instancecheck__
return self.__subclasscheck__(type(obj))
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/typing.py", line 716, in __subclasscheck__
raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks
>>> issubclass(string_list_class, …Run Code Online (Sandbox Code Playgroud) 鉴于这种:
from typing import Generic, TypeVar
T = TypeVar('T')
class Parent(Generic[T]):
pass
Run Code Online (Sandbox Code Playgroud)
我可以int从Parent[int]使用中得到typing.get_args(Parent[int])[0]。
问题变得有点复杂,如下所示:
class Child1(Parent[int]):
pass
class Child2(Child1):
pass
Run Code Online (Sandbox Code Playgroud)
为了支持任意长的继承层次结构,我提出了以下解决方案:
import typing
from dataclasses import dataclass
@dataclass(frozen=True)
class Found:
value: Any
def get_parent_type_parameter(child: type) -> Optional[Found]:
for base in child.mro():
# If no base classes of `base` are generic, then `__orig_bases__` is nonexistent causing an `AttributeError`.
# Instead, we want to skip iteration.
for generic_base in getattr(base, "__orig_bases__", ()):
if typing.get_origin(generic_base) is Parent: …Run Code Online (Sandbox Code Playgroud) 我知道我可以这样做:
\nimport typing\n\nT = typing.TypeVar("T")\n\nclass MyGenericClass(Generic[T]):\n def a_method(self):\n print(self.__orig_class__)\n\nMyOtherGeneric[SomeBaseClass]().a_method()\nRun Code Online (Sandbox Code Playgroud)\n打印SomeBaseClass。也许,我会坚持这种能力来实现我最终想要做的事情(根据修改功能T),但我现在想知道这一切是如何工作的。
本来,我想访问基类型信息(T在实例化对象时或实例化后不久,而不是在其生命周期的后期访问类内部的基本类型信息( 的值)。
作为一个具体的例子,在下面的代码中,我想要一些东西来替换其中的任何一个?n?,这样我就可以获得值SomeOtherBaseClass,这样我就可以在对象生命周期的早期也许还有一些代码也需要高于其中一行。
import typing\n\nT = typing.TypeVar("T")\n\nclass MyOtherGenericClass(Generic[T]):\n def __init__(self, *args, **kwargs):\n print(?1?)\n \n def __new__(klass, *args, **kwargs):\n print(?2?)\n\nMyOtherGenericClass[SomeOtherBaseClass]()\nRun Code Online (Sandbox Code Playgroud)\n我试图根据 的值在实例化时(或者以某种方式,在实例化之后不久)设置一些实例变量T。我正在重新考虑我的方法,因为typing模块,特别是带有泛型的东西,似乎仍然处于不稳定的开发时期。
那么\xe2\x80\xa6 可能吗?一位用户指出,至少在 3.8 中,__orig_class__在 期间设置typing._GenericAlias.__call__,但是这是如何实现的__call__调用该方法呢?什么时候会发生这种情况?
相关阅读:
\n\n假设我们要定义一个继承自 的自定义通用(基)类typing.Generic。
为了简单起见,我们希望它由单个类型变量 T来参数化。所以类的定义是这样开始的:
from typing import Generic, TypeVar
T = TypeVar("T")
class GenericBase(Generic[T]):
...
Run Code Online (Sandbox Code Playgroud)
T 有没有办法访问 的任何特定子类中的类型参数GenericBase?
该解决方案应该足够通用,能够在具有附加基础的子类中工作GenericBase,并且独立于实例化(即在类级别上工作)。
期望的结果是这样的类方法:
class GenericBase(Generic[T]):
@classmethod
def get_type_arg(cls) -> Type[T]:
...
Run Code Online (Sandbox Code Playgroud)
class Foo:
pass
class Bar:
pass
class Specific(Foo, GenericBase[str], Bar):
pass
print(Specific.get_type_arg())
Run Code Online (Sandbox Code Playgroud)
输出应该是<class 'str'>.
如果所有相关的类型注释都已完成,以便静态类型检查器可以正确推断get_type_arg.
python ×6
generics ×5
python-3.x ×3
typing ×2
base-class ×1
instanceof ×1
mypy ×1
type-hinting ×1