如何解决Python类型:有没有一种方法可以为“元素”构造类型?
我正在寻找一种创建类型的方法,该类型指示变量是某个其他集合的 元素。我知道集合类型:
from typing import Collection
Foo = Collection[Bar]
相反,我想做相反的事情,即
Bar = Element[Foo]
有没有办法做到这一点?
我想到的用例是能够实现以下功能:
import numpy as np
from gym.spaces import Space,Box,Discrete
Element = ... # some type definition
def func(x: Element[Box],i: Element[Discrete]) -> Element[Box]:
""" asserts are implied by the type annotations """
assert isinstance(x,np.ndarray)
assert isinstance(i,int)
return x * i
以下是使用gym.spaces
的详细示例:
from gym.spaces import Space,Discrete
box = Box(low=0,high=1,shape=(3,))
dsc = Discrete(5)
x = box.sample() # example: x = array([0.917,0.021,0.740],dtype=float32)
i = dsc.sample() # example: i = 3
def check(space: Space,y: Element[Space]) -> Element[Space]:
if y not in space:
raise ValueError("y not an element of space")
return y
x = check(box,x)
i = check(dsc,i)
解决方法
这如何为您工作?
from abc import ABC,abstractmethod
from typing import Generic,TypeVar,NewType
T = TypeVar("T")
DiscreteT = NewType("DiscreteT",int)
BoxT = NewType("BoxT",float)
class Space(ABC,Generic[T]):
@abstractmethod
def sample(self) -> T: ...
def __contains__(self,item: T) -> bool: ...
class Discrete(Space[DiscreteT]):
def __init__(self,n: int) -> None: ...
def sample(self) -> DiscreteT: ...
class Box(Space[BoxT]):
def __init__(self,low: float,high: float) -> None: ...
def sample(self) -> BoxT: ...
def check(space: Space[T],y: T) -> T:
if y in space:
raise ValueError("y not an element of space")
return y
box = Box(low=0,high=1)
dsc = Discrete(5)
x = box.sample()
i = dsc.sample()
# Assumes that these lines are run separately for example's sake,such that assignment from one doesn't impact lines later.
x = check(box,x) # Passes mypy.
i = check(dsc,i) # Passes mypy.
x = check(box,i) # Fails mypy: error: Cannot infer type argument 1 of "check".
i = check(box,x) # Fails mypy: error: Cannot infer type argument 1 of "check".
other_dsc = Discrete(0)
i = check(other_dsc,i) # Passes mypy,even though `i` came from `dsc`. Don't know if it is possible for this to be caught at type-check time.
我将Space
,Discrete
和Box
的类型提示写为type stubs,这样,如果您不控制{的来源,就可以添加它们{1}}。您应该可以轻松地将gym.sources
参数添加到shape
。
这里的基本思想是我们用其可以包含的元素类型对Box
进行参数化。我们使用Space
来使空间元素从根本上成为子类型(从NewType
采样的元素是Discrete
,并且具有int
属性)而不会牺牲保证int
强制执行,因为check
是从y
采样的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。