Python 中的高级类型提示 - 当类型不够具体时如何避免 mypy 生气

问题描述 投票:0回答:1

我有一些返回字典的函数:

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 type-hinting python-typing
1个回答
0
投票

使用像

mypy
这样的类型检查器时,您应该始终尝试定义预期的类型 尽可能精确。然而,在某些情况下,定义所有 预期的类型会适得其反,有时甚至是不可能的。 对于这些情况,您可能需要指定广泛的类型提示,例如
Any
,或者
object
,虽然这些应该尽量避免。

解决
mypy
问题的解决方案

您的代码特别包含一个具有混合类型的嵌套字典,其中

mypy
根据您的函数签名和内部处理发现不明确 的功能。您可以通过执行以下操作来解决
mypy
警告 变化:

  1. 使用 TypedDict 进行精确类型定义:当您想要 指定字典中键的类型。这让

    TypedDict
    能够理解 字典中需要哪些键及其相应的值类型。
    
    

  2. 显式类型检查和使用

    mypy方法

    :在访问嵌套键之前,
    检查键是否存在或使用字典的
    .get()方法可以 如果密钥不存在,则返回
    .get()
    (或您提供的默认值)。 这是一种更安全的访问字典中值的方式,并且可以满足
    None
    您已经处理了潜在的
    mypy
    s。
    
    

  3. 字典值的可选类型

    :表示字典值, 特别是在嵌套结构中,可以通过使用 KeyError

    None
    
    

  4. 使用上述解决方案修改后的示例

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

© www.soinside.com 2019 - 2024. All rights reserved.