Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用装饰器获取类泛型类型的运行时类型?_Python_Python 3.x_Generics_Annotations_Typing - Fatal编程技术网

Python 如何使用装饰器获取类泛型类型的运行时类型?

Python 如何使用装饰器获取类泛型类型的运行时类型?,python,python-3.x,generics,annotations,typing,Python,Python 3.x,Generics,Annotations,Typing,我有一个泛型类,比如 从输入import Generic、TypeVar、List T=TypeVar('T') @我的装饰师 类Foo(泛型[T]): 通过 f:Foo[int]=Foo() g:Foo[List[float]]=Foo() 有没有一种干净的方法可以在decorator中获取构造函数调用的类型注释Foo[int],Foo[List[float]]?我想在运行时做一些类型检查 我可以通过decorator访问Foo的构造函数调用,甚至可以通过使用inspect.stack()和

我有一个泛型类,比如

从输入import Generic、TypeVar、List
T=TypeVar('T')
@我的装饰师
类Foo(泛型[T]):
通过
f:Foo[int]=Foo()
g:Foo[List[float]]=Foo()
有没有一种干净的方法可以在decorator中获取构造函数调用的类型注释
Foo[int],Foo[List[float]]
?我想在运行时做一些类型检查

我可以通过decorator访问
Foo
的构造函数调用,甚至可以通过使用
inspect.stack()
inspect.getsource(我的框架)
以非常不寻常的方式获得构造函数调用的代码行
f:Foo[int]=Foo()
。然后我可以通过一些字符串操作获得
Foo[int]

除此之外,这是一种非常肮脏的方法,它只获取字符串形式的类型。但我需要真正的类型。在本例中,我可以使用
eval()
来“解析”字符串并将其转换为类型。但这不适用于自定义类,如本例中所示:

从输入import Generic、TypeVar、List
T=TypeVar('T')
分类栏:
通过
@我的装饰师
类Foo(泛型[T]):
通过
h:Foo[List[Bar]]=Foo()
在这种情况下,我不能使用
eval()
,因为我不知道如何获得正确的
上下文。
我喜欢得到类似于
my_file.Foo[typing.List[my_file.Bar]
的东西,它允许我在运行时进行类型检查


那么有没有干净的方法呢?或者是否至少有一种(肮脏的)方法来获取正确的上下文,以便
eval()
来“解析”字符串?

TL;DR:这不可能在
\uuuu init\uuuu>中获得泛型的运行时类型,但我们可以在CPython实现中获得足够的接近度

  • 要在类中仅使用decorator处理此问题,您应该将调用更改为
    h=Foo[List[Bar]]()
    ,以便decorator可以独立于保存返回对象的变量访问typehint

  • 指示泛型类的类实例在初始化后具有可用的
    \uuuuu orig\u class\uuuuu
    属性。此属性在init之后设置(请参阅)

  • 因此,如果我们编写一个类装饰器,装饰器应该修改源类,以便在运行时设置
    \uuuu orig\u class\uuuu
    属性时基本侦听。不过,这在很大程度上依赖于未记录的实现细节,在Python的未来版本或其他实现中可能不会以同样的方式工作

    def my_decorator(cls):
    原始基准=cls.\uu原始基准__
    genericType=原始基[0]
    类别cls2(cls,genericType):
    定义初始化(self,*args,**kwargs):
    超级(cls2,自我)。\uuuuuuuuuuuuuuuuuu初始(*args,*kwargs)
    定义设置属性(自身、名称、值):
    对象。设置属性(自身、名称、值)
    如果名称=“\uuuuu原始类”:
    打印(“运行时泛型类型为”+str(获取参数(self.\uuu orig\u类)))
    cls2.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu基
    返回cls2
    
    然后:

    h=Foo[List[Bar]]() 运行时泛型类型为(typing.List[\uuuu main\uuuu.Bar],)
    相关:。您能提供
    my_decorator
    的示例代码吗?现在还不清楚你想要实现什么。