jon*_*ach 13 python mypy python-typing
是否typing.TypedDict允许额外的钥匙?如果某个值具有 TypedDict 定义中不存在的键,该值是否会通过类型检查器?
jon*_*ach 12
这取决于。
PEP-589, 的规范TypedDict,明确禁止额外的密钥:
TypedDict对象构造中包含的额外键也应该被捕获。在此示例中,导演键未在 Movie 中定义,并且预计会从类型检查器中生成错误:
Run Code Online (Sandbox Code Playgroud)m: Movie = dict( name='Alien', year=1979, director='Ridley Scott') # error: Unexpected key 'director'
[我强调的]
类型检查器 mypy、pyre、pyright 根据规范实现这一点。
但是,有可能接受带有额外键的值。这是因为 TypedDicts 的子类型是允许的,并且子类型可能实现额外的键。PEP-589 仅禁止在对象构造中(即文字赋值中)使用额外的键。由于任何符合子类型的值始终被视为符合父类型,并且可以从子类型向上转换为父类型,因此可以通过子类型引入额外的键:
from typing import TypedDict
class Movie(TypedDict):
name: str
year: int
class MovieWithDirector(Movie):
director: str
# This is illegal:
movie: Movie = {
'name': 'Ash is purest white',
'year': 2018,
'director': 'Jia Zhangke',
}
# This is legal:
movie_with_director: MovieWithDirector = {
'name': 'Ash is purest white',
'year': 2018,
'director': 'Jia Zhangke',
}
# This is legal, MovieWithDirector is a subtype of Movie
movie: Movie = movie_with_director
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,我们看到相同的值有时可以被视为符合Movie打字系统,有时则不然。
作为子类型化的结果,将参数键入为某个 TypedDict 并不能防止额外的键,因为它们可能是通过子类型引入的。
如果您的代码对额外键的存在很敏感(例如,如果它在参数上使用param.keys(),param.values()或),则当存在额外键时可能会导致问题。此问题的解决方案是要么处理参数上实际存在额外键的特殊情况,要么使代码对额外键不敏感。len(param)TypedDictparam
如果您想测试您的代码是否对额外的键具有鲁棒性,则不能简单地在测试值中添加键:
def some_movie_function(movie: Movie):
# ...
def test_some_movie_function():
# this will not be accepted by the type checker:
result = some_movie_function({
'name': 'Ash is purest white',
'year': 2018,
'director': 'Jia Zhangke',
'genre': 'drama',
})
Run Code Online (Sandbox Code Playgroud)
解决方法是使类型检查器忽略该行或为您的测试创建一个子类型,仅为您的测试引入额外的键:
class ExtendedMovie(Movie):
director: str
genre: str
def test_some_movie_function():
extended_movie: ExtendedMovie = {
'name': 'Ash is purest white',
'year': 2018,
'director': 'Jia Zhangke',
'genre': 'drama',
}
result = some_movie_function(test_some_movie_function)
# run assertions against result
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5828 次 |
| 最近记录: |