使用 `Literal` 进行类型提示然后在运行时验证的好模式是什么?

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

假设我有课:

from typing import Literal


class Computer:
    def __init__(self, operation: Literal['floor', 'ceil', 'square']):
        if operation not in ('floor', 'ceil', 'square'):
            raise ValueError(f'Invalid operation "{operation}"')
        self._operation = operation

    # ... lots of methods that use `self._operation`, e.g.
    def is_much_larger(self, value: float) -> bool:
        if self._operation == 'square':
            if value > 1:
                return True
            else:
                return False
        else:
            return False

我想将可行值列表(即

'floor', 'ceil', 'square'
)保留在一个地方。有什么好的食谱吗?

MyPy docs 通过

assert_never
的建议展示了一些想法,但这只是 MyPy 在运行时之前给出错误,而不是作为维护单个值列表的方法。

python python-3.x type-hinting mypy
2个回答
1
投票

您可以使用输入模块内省这些参数。

>>> import typing
>>> Operation = typing.Literal['floor', 'ceil', 'square']
>>> typing.get_args(Operation)
('floor', 'ceil', 'square')

您可以使用类型别名,然后使用

typing.get_args
获取所需的值,例如:

import typing

# in Python >= 3.10 , use explicit type alias:
# Operation: typing.TypeAlias = typing.Literal['floor', 'ceil', 'square'
Operation = typing.Literal['floor', 'ceil', 'square']


class Computer:
    def __init__(self, operation: Operation:
        if operation not in typing.get_args(Operation):
            raise ValueError(f'Invalid operation "{operation}"')
        self._operation = operation

    # ... lots of methods that use `self._operation`, e.g.
    def is_much_larger(self, value: float) -> bool:
        if self._operation == 'square':
            if value > 1:
                return True
            else:
                return False
        else:
            return False

0
投票

另一种方法是使用

Enum

这将所有选项封装在一起并极大地简化了类型提示。但是,这意味着每当您调用该函数时都必须使用此

Enum
。如果你有很多功能并且有很多不同的
Enums
,这会有点烦人。

from enum import Enum, auto

class Operation(Enum):
    # All caps by convention
    FLOOR = auto()  
    CEIL = auto()   
    SQUARE = auto()  

class Computer:
    # Type hint is much simpler, especially if there are many options
    def __init__(self, operation: Operation):
        # No need for ValueError check
        self._operation = operation

    def is_much_larger(self, value: float) -> bool:
        # Example usage, always have to compare to Operation.SOMETHING
        if self._operation == Operation.SQUARE:
            return value > 1
        return False

注意:

auto()
自动为每个成员分配唯一的int值(即1、2、3...)

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