Skip to main content

数据类型

👍enum 模块

基本示例

from enum import Enum

class TrafficLight(Enum):
RED = 1
YELLOW = 2
GREEN = 3
# YELLOW = 1 #常见错误:将枚举成员的值设置为相同类型
# RED = [255, 0, 0] # 常见错误:错误地将枚举成员的值设置为可变类型
# YELLOW = None # 常见错误:错误地将枚举成员的值设置为None、False、True等
# 使用枚举
light = TrafficLight.RED

# if light == 1 常见错误:错误地使用Enum成员进行比较
if light == TrafficLight.RED:
print("红灯,停车")
elif light == TrafficLight.YELLOW:
print("黄灯,准备")
else:
print("绿灯,通行")

是否使用Enum取决于你项目的需求和代码的复杂度。你可能觉得不需要它,尤其是在简单的场景下,直接使用字符串或整数常量看似足够。但是,Enum有以下几个优势:

1. 增加可读性

当你看到Color.RED时,比直接看到一个1'red'更容易理解。Enum能让你的代码更具语义化,避免硬编码的常量值。

例如:

status = Status.SUCCESS  # 一目了然:状态是成功

相比:

status = 1  # 需要额外判断 1 是什么意义

2. 减少错误

使用Enum可以避免常见的错误,比如不小心使用了错误的值或者字符串拼写错误。Enum成员是唯一的,且不可变的,能够防止无意间改变它们的值。

比如,如果你用了Status.SUCCESS = 1,然后在后续代码中某处错误地设置了Status.SUCCESS = 2,你会收到警告或报错,而不是默默覆盖,产生潜在的 bug。

3. 类型安全

使用Enum可以确保变量的值只来自于枚举成员,而不会误用其他类型的值(如普通的数字、字符串等)。这对于大型项目来说尤其重要,因为它能有效地避免一些奇怪的 bug。

比如:

def set_color(color: Color):
if not isinstance(color, Color):
raise ValueError("Invalid color")

4. 易于扩展和维护

随着项目的扩展,你可能会有更多的常量值需要添加,Enum让这种扩展变得更清晰、更系统化。你不再需要在多个地方定义相同的常量,所有的常量都集中在一个地方。

比如,随着系统需求变化,你可能需要扩展交通灯的状态:

class TrafficLight(Enum):
RED = 1
YELLOW = 2
GREEN = 3
FLASHING = 4 # 新增状态

5. 集成与协作的优势

在多人开发的团队中,使用Enum可以提高协作性。它使得每个成员的代码中常量的含义更加清晰,减少误解或重复定义的问题。

6. 可迭代、可比较

Enum支持迭代、比较等操作,允许你灵活处理。例如,你可以遍历所有的Enum成员,或者比较它们的顺序。

for state in TrafficLight:
print(state)

typing 模块

typing 模块提供高级类型支持:

from typing import List, Dict, Tuple, Optional, Union

# 容器类型
names: List[str] = ["Alice", "Bob"]
person: Dict[str, Union[str, int]] = {"name": "Alice", "age": 30}

# 可选类型
def get_age(name: str) -> Optional[int]:
if name == "Alice":
return 30
return None

# 类型别名
UserId = int
user_id: UserId = 1001

泛型 (Generic)

创建可复用的类型安全容器:

from typing import TypeVar, Generic, List

T = TypeVar('T')

class Stack(Generic[T]):
def __init__(self) -> None:
self._items: List[T] = []

def push(self, item: T) -> None:
self._items.append(item)

def pop(self) -> T:
return self._items.pop()

# 使用
int_stack: Stack[int] = Stack()
int_stack.push(42)

Literal 字面量类型

限制值只能是特定的字面量:

from typing import Literal

def set_mode(mode: Literal["read", "write", "append"]) -> None:
print(f"Mode set to: {mode}")

set_mode("read") # 正确
set_mode("delete") # 类型检查器会报错

# 多种类型的字面量
def process_flag(flag: Literal[True, False, 0, 1]) -> None:
pass