python - 如何为类型参数设置 python 类型
问题描述
我想为作为参数传递的 Python 类型正确添加类型。例如,让我们假设我们想为以下函数添加类型:
def do_something_based_on_types(
...
type_name: str,
str_to_type_mapping: Dict[str, Any], # what instead of Any?
):
...
object = str_to_type_mapping[type_name]()
...
我们希望将映射从str
类型传递到我们希望构造选定类的对象的类型。这种情况下的正确类型是什么(而不是Any
在代码示例中使用)。
解决方案
你的例子是非常动态的。由于 Python 类型注解的主要目的是支持静态分析,因此它们在这里为我们提供的功能是有限的。但是,我确实认为我们可以做得更好Any
!
(注意:为防止混淆,我将在您的代码段中引用名为 的变量object
,my_object
当我使用 时object
,我指的是 Python 类型)。
使用打字。类型
由于您提到提供的字典中的值应该是可以启动的类型,因此合理的类型注释将是Dict[str, Type[object]]
or Dict[str, Type]
,其中后者等效于Dict[str, Type[Any]]
. 第一个是最严格的,它将限制类型检查器允许您对my_object
变量执行的操作。第二个只比 plain 稍微好一点Any
,尽管它会在调用者意外提供实例而不是类型时警告调用者。
或打字。可调用?
从您提供的片段中,使用字典值的唯一方法是创建一个新实例。类型不是唯一可以做到这一点的东西。实际上,任何接受零参数并返回对象的可调用(普通函数,类方法)也足够了。因此 usingCallable[[], object]
将为函数的调用者提供更大的灵活性,并且还会在传递没有零参数构造函数的类型时发出警告。我更喜欢这个,Type
因为它看起来更安全,更符合 Python 的鸭式打字精神。
比普通物体更好的东西?
这两种解决方案都有一个限制,即在您的函数内部,我们对my_object
. 在一般情况下,isinstance
每次我们执行对象类型不支持的操作时,我们都“被迫”进行检查。但是,也许在您的用例中,单个字典不应该包含任何类型。可能是这样的:
- 所有类型都有一个共同的基类,比如
MyBase
. - 所有类型都应该支持一组通用的操作(方法或属性)。
在情况 (1) 中,我们可以将object
type 替换为 type MyBase
。类型检查器应该能够MyBase
安全地使用所支持的操作,并在提供的字典包含其他类型时发出警告。
对于情况(2),typing.Protocol
可以帮助我们。您可以使用所需的操作定义自定义协议,并将其添加到类型注释中:
class MyCustomProto(Protocol):
foo: int
def bar(self) -> str: ...
现在类型检查器应该知道my_object
应该有整数属性
foo
和bar
返回字符串的方法。请注意,它已Protocol
添加到 Python 3.8,并且可通过typing-extensions包用于以前的版本。
字典与打字。映射
和你的问题没有直接关系,但是如果你只用字典来阅读,你应该考虑用Dict
类型替换Mapping
。这允许调用者提供除 dict 子类之外的任何映射类型(在实践中不太可能发生)。但更重要的是,它会在您意外修改提供的映射时发出警告,这可能会导致难以发现错误。因此,我的最终建议是Mapping[str, Callable[[], <X>]
,<X>
成为或中object
的一个。MyCustomProto
MyBase
推荐阅读
- android - 使用 FFmpeg 的视频压缩在 android 10 上不起作用
- google-bigquery - 在 BigQuery 中将数据插入/创建分片/通配符表
- extjs - 当 ExtJS 6.7 中的第一个数字为 0 时,datepickerfield 自动切换日期和月份
- azure - Set-AzActionGroup:异常类型:ErrorResponseException
- python-3.x - 仅在 python 中打印前 25 个索引
- azure - 带有 AAD 的 Azure SQL DB - 有没有办法获得只读访问权限
- vb.net - API REST Verbe 类型使用 GET 而不是 POST
- sql - 我们如何在 SQLITE 中将 clob 字段的子字符串转换为日期时间?
- python - 在python中将二进制图像缩小到非零区域
- html - 在两个媒体查询之间平滑缩放 SVG