如何在Python 3中将参数传递给自定义静态类型提示?

时间:2018-09-03 17:05:13

标签: python python-3.x python-3.6 python-3.5 python-typing

我是Python 3的忠实拥护者和拥护者,我一直在使用它们一段时间,没有任何问题。

我遇到了一个我似乎无法编译的新案例。如果要定义自定义类型,然后定义其参数怎么办?

例如,这在Python 3中很常见:

from typing import List, NewType
CustomObject = NewType('CustomObject', List[int])

def f(data: List[CustomObject]):
    # do something

但这不会编译:

class MyContainer():
    # some class definition ...

from typing import NewType
SpecialContainer = NewType('SpecialContainer', MyContainer)

def f(data: SpecialContainer[str]):
    # do something

我认识到SpecialContainer在这种情况下从技术上来说是一个函数,但是不应在类型签名的上下文中将其视为一个函数。第二个代码段以TypeError: 'function' object is not subscriptable失败。

1 个答案:

答案 0 :(得分:1)

编译我的代码示例

您必须从头开始设计类,以接受静态类型提示。这不符合我的原始用例,因为我试图声明3rd party类的特殊子类型,但是它编译了我的代码示例。

from typing import Generic, TypeVar, Sequence, List

# Declare your own accepted types for your container, required
T = TypeVar('T', int, str, float)

# The custom container has be designed to accept types hints
class MyContainer(Sequence[T]):
    # some class definition ...

# Now, you can make a special container type
# Note that Sequence is a generic of List, and T is a generic of str, as defined above
SpecialContainer = TypeVar('SpecialContainer', MyContainer[List[str]])

# And this compiles
def f(data: SpecialContainer):
    # do something

对第3方类进行子类化

我的初衷是创建一个类型提示,以解释函数f()如何获取pd.DataFrame对象,该对象由整数索引并且其单元格均为字符串。使用以上答案,我想出了一种人为表达的方式。

from typing import Mapping, TypeVar, NewType, NamedTuple
from pandas import pd

# Create custom types, required even if redundant
Index = TypeVar('Index')
Row = TypeVar('Row')

# Create a child class of pd.DataFrame that includes a type signature
# Note that Mapping is a generic for a key-value store
class pdDataFrame(pd.DataFrame, Mapping[Index, Row]):
    pass

# Now, this compiles, and explains what my special pd.DataFrame does
pdStringDataFrame = NewType('pdDataFrame', pdDataFrame[int, NamedTuple[str]])

# And this compiles
def f(data: pdStringDataFrame):
    pass

值得吗?

  • 如果您要编写类似于SequenceMappingAny之类的容器的自定义类,请继续使用。免费将类型变量添加到类定义中。

  • 如果您要注明未实现类型提示的第三方类的特定用法:

    • 尝试使用现有的类型变量来阐明您的观点,例如MyOrderedDictType = NewType('MyOrderedDictType', Dict[str, float])
    • 如果这不起作用,则必须使用琐碎的子类和类型变量来使名称空间混乱,以获取要编译的类型提示。最好使用文档字符串或注释来说明您的情况。