Python类型.TypedDict.如何将非必需密钥转换为必需密钥



下面的代码定义了一个带有可选键的TypedDict。如果某个键不存在,中间的if语句将引发异常,这意味着只有在该键存在的情况下才会执行下一行。Pylance似乎无法自动理解这个逻辑。我该怎么处理?以某种方式将新类型重新分配给相同的Dict

output_dict_type = TypedDict(
'some description',
{
'id': str
'name': str
},
total=False
)
my_dict:output_dict_type = {
'id': 'foo'
}
if not my_dict.get('name'):
raise Exception('name is required')
if my_dict['name'] == 'John': # type error: "name" is not a required key...
do_stuff()

这可能是一个练习的好地方"请求原谅比寻求许可更容易";。我的意思是将密钥获取封装在try/except块中。如果密钥不存在,则抛出异常,随后的代码将保证提取的密钥存在。

from typing import Optional, TypedDict
class OutputType(TypedDict, total=False):
id: str
name: Optional[str]
my_dict: OutputType = ...
# guards
try:
name = my_dict['name']
except KeyError:
# name local var not initialised here
raise Exception('name is required')
# name local var guaranteed to be initialised here
# since you cannot guarantee that name will be a str, we still have 
# to do a type check
if not isinstance(name, str):
raise Exception('name must be str')
# happy path code
if name == 'John':
...

如果您不能依赖于输入数据的精确格式,那么您应该编写一些自定义的序列化逻辑。这个逻辑可以隐藏在另一个函数中,可以处理所有的类型检查和其他验证。然后它可以返回一个完全类型化的数据类,您可以继续处理数据。

from dataclasses import dataclass
@dataclass
class OutputType:
id: str
name: str
@classmethod
def deserialise(cls, id=None, name=None) -> 'OutputType':
assert isinstance(id, str), 'id must be present and a string'
assert isinstance(name, str), 'name must be present and a string'
return Output(id, name)
output_dict: dict[str, Any] = ...
output = OutputType.deserialise(**output_dict)
if output.name == 'John':
...

最新更新