我有一些返回字典的函数:
def get_metadata_from_file(filepath:str)->dict[str, bool|dict[str, Any]]:
'''Get metadata about a file if it exists'''
answer = {}
if os.path.isfile(filepath):
answer['exists'] = True
answer['metadata'] = { dict of metadata attributes }
else:
answer['exists'] = False
answer['metadata'] = {}
return answer
后来在其他功能中我遇到了问题:
def get_creation_time(filepath:str)->str|None:
metadata = get_metadata_from_file(filepath)
if metadata['exists']:
return metadata['metadata']['created_at'] # Mypy gets angry here
else:
return None
显然,程序的逻辑处理文件不存在的情况,但 Mypy 担心
metadata['metadata']['created_at']
键可能不存在/metadata['metadata'] 将是一个布尔值。
我确定有解决方案,推荐的方法是什么?
使用像
mypy
这样的类型检查器时,您应该始终尝试定义预期的类型
尽可能精确。然而,在某些情况下,定义所有
预期的类型会适得其反,有时甚至是不可能的。
对于这些情况,您可能需要指定广泛的类型提示,例如 Any
,或者
object
,虽然这些应该尽量避免。
mypy
问题的解决方案您的代码特别包含一个具有混合类型的嵌套字典,其中
mypy
根据您的函数签名和内部处理发现不明确
的功能。您可以通过执行以下操作来解决 mypy
警告
变化:
使用 TypedDict 进行精确类型定义:当您想要 指定字典中键的类型。这让
TypedDict
能够理解
字典中需要哪些键及其相应的值类型。
mypy
方法
:在访问嵌套键之前, 检查键是否存在或使用字典的
.get()
方法可以
如果密钥不存在,则返回 .get()
(或您提供的默认值)。
这是一种更安全的访问字典中值的方式,并且可以满足None
您已经处理了潜在的mypy
s。
:表示字典值,
特别是在嵌套结构中,可以通过使用 KeyError
来
None
。
Optional[type]
上面重构的代码应该可以解决您遇到的
from typing import TypedDict, Optional, Any
import os
class FileMetadata(TypedDict):
exists: bool
metadata: Optional[dict[str, Any]] # Adjust Any to be more specific if possible
def get_metadata_from_file(filepath: str) -> FileMetadata:
"""Get metadata about a file if it exists"""
answer: FileMetadata = {'exists': False, 'metadata': None}
if os.path.isfile(filepath):
answer['exists'] = True
# Example metadata dict. Replace with actual metadata extraction.
answer['metadata'] = {'created_at': '2023-01-01'}
return answer
def get_creation_time(filepath: str) -> Optional[str]:
metadata = get_metadata_from_file(filepath)
if metadata['exists'] and metadata['metadata']:
# Use .get() for safer access to the 'created_at' key
return metadata['metadata'].get('created_at')
return None
问题:
mypy