对于python3中的类型注释,我有点困惑,特别是对于吐出生成类型的生成器函数。我认为,具体来说,我的困惑来自typing.Type
的文档。这是我的代码段:
from collections import UserList
UserType = TypeVar('UserType')
def TypeSequence(usertype: Type[UserType]) -> Type[Sequence[UserType]]:
class Result(UserList):
... # Cut out the implementation for brevity's sake
return Result
生成的“ TypeSequence”正在执行类型检查,以便仅生成可序列化的数据结构,对此问题并不重要。重点是,您应该能够执行以下操作:
MyIntSequence = TypeSequence(int)
MyIntSequence((1, 2, 3)) -> [1, 2, 3] with type Sequence[Int]
MyTupleSequence = TypeSequence(tuple)
MyTupleSequence(((1, 2), (3, 4))) -> [(1, 2), (3, 4)] with type Sequence[tuple]
我的问题:我提供的类型注释正确吗?
我的怀疑主要源于PyCharm,它无法提供由我的自定义生成器函数生成的类型。 PyCharm可能是一个问题,但我对此表示怀疑,因为它对于标准库非常有效,该标准库几乎使用同样复杂的类型注释。
一个简单的例子,其中类型推断似乎失败了:
请注意,此列表版本与此相反:
我也对“ TypeSequence”实际上做什么有很多疑问。我对该实现进行了重新编写,以使内容更简短,但是这里是完整的实现。它执行一些类型强制和类型检查:
from collections import UserList
from typing import (Optional, Any, Sequence, Callable, Hashable, Dict, Mapping, Type, TypeVar,
)
UserType = TypeVar('UserType')
def TypeSequence(usertype: Type[UserType]) -> Type[Sequence[UserType]]:
class Result(UserList):
def __init__(self, *args):
from collections import Iterable
if len(args) == 0:
super(Result, self).__init__()
elif len(args) == 1:
if not isinstance(args[0], Iterable):
raise ValueError("Not a iterable")
if issubclass(usertype, tuple) and hasattr(usertype, "_fields"):
if any(not isinstance(x, Iterable) for x in args[0]):
raise ValueError("Invalid initializer for named tuple")
if len(args[0]) != len(usertype._fields):
raise ValueError(f"Not enough values to initialize {usertype}")
seq = (usertype(*x) for x in args[0])
else:
seq = (usertype(x) for x in args[0])
super(Result, self).__init__(seq)
Result.__name__ = f"TypeSequence[{usertype.__name__}]"
return Result
我认为这不会增加任何问题,但是您可以:D
答案 0 :(得分:1)
TLDR:对于要实例化的任何类型,请使用# UNTESTED. Note that TRUNCATE is IRREVERSIBLE.
Invoke-SqlCmd -Query "TRUNCATE TABLE $SQLSchema.$SQLTable" `
-ServerInstance $SQLServer -Database $SQLDatabase -Credential $SQLCredential -Force
而不是Callable
。具体来说,要明确说明返回类型签名。
Type
def TypeSequence(
usertype: Type[UserType]
) -> Callable[[Iterable[UserType]], Sequence[UserType]]
...
是抽象类型,因此无法实例化Type[Sequence[UserType]]
。 Sequence
将实例化标记为无效:
mypy
为正确起见,请将返回类型注释为XSeq = TypeSequence(X)
x_seq = XSeq([X()]) # error: Too many arguments for "Sequence"
或List
。
UserList
除了类型正确性之外,请注意,PyCharm通常不理解复杂的def TypeSequence(usertype: Type[UserType]) -> Type[UserList[UserType]]:
...
关系。显示函数的类型表明Type
简化为Type[UserList[UserType]]
。
使用Type[UserList]
可以表示复杂类型的实例化。可以定义精确的签名,包括Callable
而不是Sequence
:
UserList