python 变量类型注释
文章目录
- 1. 基础的类型注释
- 1.1 变量类型注释
- 1.2 函数类型注释
- 2. 进阶使用
- 2.1 使用 Optional 和 Union
- 2.3 List, Tuple, Dict,Sequence 等容器类型
- 2.4 Callable 用法
- 2.5 类型别名
- 2.6 NewType 用法
- 3 总结
Python 类型注释(Type Hints)是 Python 3.5开始 引入的一项功能,旨在提高代码的可读性、可维护性,并帮助静态分析工具检查代码中的类型错误。虽然 Python 是动态类型语言,但通过类型注释,我们可以显式地标注变量和函数的预期类型,从而使代码更容易理解,并获得类型检查工具(如 mypy)的帮助。
1. 基础的类型注释
在 Python 中,类型注释通常使用 :
来指定变量或函数参数的类型,使用 ->
来指定函数返回值的类型。
1.1 变量类型注释
Python 3.6+ 支持为变量添加类型注释。它通常出现在变量赋值时,注释类型后跟 :
,然后是实际的赋值操作。
x: int = 10 # x 是一个整数
y: str = "hello" # y 是一个字符串
z: float = 3.14 # z 是一个浮动数
1.2 函数类型注释
对于函数,我们可以在函数的参数
和返回值
上添加类型注释。参数类型注释出现在参数名后面,返回类型注释出现在函数签名的->
后面。
def greet(name: str) -> str:
return "Hello, " + name
def add(a: int, b: int) -> int:
return a + b
在这个例子中,greet 函数接受一个字符串类型的参数 name,并返回一个字符串;add 函数接受两个整数类型的参数 a 和 b,并返回一个整数。
2. 进阶使用
2.1 使用 Optional 和 Union
有时候我们会希望一个参数或返回值是几种不同类型中的一种
,这时我们可以使用 Union
。如果某个值是可选的
(例如,它可以是一个类型或 None
),可以使用 Optional
。
Union 用法
Union 用于表示多种类型中的任意一种。它通常用于表示参数或返回值可以接受多种类型
。
from typing import Union
def process_data(data: Union[str, int]) -> str:
if isinstance(data, str):
return data.upper()
elif isinstance(data, int):
return str(data)
data 可以是一个字符串或一个整数。
Optional 用法
Optional[X]
只是 Union[X, None]
的简写形式,表示某个值可以是类型 X 或 None
。
from typing import Optional
def find_item(name: str) -> Optional[int]:
# 如果找不到则返回 None,否则返回一个整数
if name == "item1":
return 1
return None
在这个例子中,find_item 函数返回的值可以是 int 或 None。
案例
def get_affine_transform(
size: Union[Tuple[float], List[float]],
rotation: float,
out_size: Union[Tuple[float], List[float]],
inverse: bool = False,
center_shift: Optional[Union[Tuple[float], List[float]]] = (0, 0),
pre_resize_scale: Optional[float] = -1.0,
crop_kwargs: Optional[dict] = None,
):
def __init__(
self,
save_dir: str,
name_prefix: Optional[str] = "",
save_interval: Optional[int] = 1,
interval_by: Optional[str] = "epoch",
save_on_train_end: Optional[bool] = True,
strict_match: Optional[bool] = False,
mode: Optional[str] = None,
monitor_metric_key: Optional[str] = None,
best_refer_metric: Optional[Union[dict, EvalMetric]] = None,
task_sampler=None,
save_hash: bool = True,
only_save_ddp: bool = False,
keep_n: Optional[int] = None,
):
2.3 List, Tuple, Dict,Sequence 等容器类型
Python 允许为标准容器类型(如列表、元组、字典
等)添加类型注释。可以通过 typing 模块中的类型来为容器指定具体的元素类型。
List
from typing import List,Tuple,Dict
def get_names(names: List[str]) -> int:
return len(names)
names 是一个字符串类型的列表,函数返回一个整数。
Tuple
Tuple 用于表示固定长度、不同类型的元素的集合。
from typing import Tuple
def get_point() -> Tuple[int, int]:
return (10, 20)
get_point 函数返回一个元组,包含两个整数。
Dict
Dict 用于表示键值对容器。
from typing import Dict
def get_person_info() -> Dict[str, str]:
return {"name": "Alice", "age": "25"}
get_person_info 函数返回一个字典,键和值都是字符串类型。
Sequence
- Sequence 表示一个可以被索引的容器(
而不局限于列表或元组
)。它使得类型更加灵活,并允许接受任何符合序列特性
的数据类型。 - Sequence 是一个更宽泛的接口,表示所有具有序列性质的对象,包括不可变的对象(如元组和字符串)以及可变对象(如列表)
from typing import List, Sequence
# List 仅限于列表
def append_to_list(lst: List[int]) -> None:
lst.append(4)
# Sequence 可以接受任何序列类型(包括列表、元组、字符串)
def print_first(seq: Sequence[int]) -> None:
print(seq[0])
# Test with List
lst = [1, 2, 3]
append_to_list(lst) # 正常
# Test with Sequence
print_first(lst) # 输出 1
案例
def __init__(
self,
metric_update_func: Callable,
metrics: Optional[Sequence] = None,
filter_condition: Optional[Callable] = None,
step_log_freq: Optional[int] = 1,
reset_metrics_by: Optional[str] = "epoch",
epoch_log_freq: Optional[int] = 1,
log_prefix: Optional[str] = "",
step_storage_freq: Optional[int] = -1,
epoch_storage_freq: Optional[int] = -1,
storage_key: Optional[str] = "monitor_obj",
):
def compute_box_3d_lidar(
dim: Union[np.ndarray, List],
location: Union[np.ndarray, List],
yaw: np.ndarray,
with_size: bool = False,
) -> np.ndarray:
def rearrange_det_dense_head_out(
reg_pred: List[torch.Tensor],
cls_pred: List[torch.Tensor],
) -> Tuple[torch.Tensor, torch.Tensor]:
2.4 Callable 用法
Callable 用于表示一个可调用对象,类似函数
。你可以指定函数的参数类型和返回值类型
from typing import Callable
def execute_operation(op: Callable[[int, int], int], a: int, b: int) -> int:
return op(a, b)
def add(x: int, y: int) -> int:
return x + y
result = execute_operation(add, 3, 4) # 传入 add 函数,返回 7
Callable[[int, int], int]
表示一个函数,它接受两个 int 类型
的参数,并返回一个 int 类型
的值。
@abstractmethod
def __call__(
self,
batch: Union[Tuple[Any], List[Any], object],
model: torch.nn.Module,
device: Union[int, None],
optimizer=None,
batch_begin_callback: Callable = None, # 函数
batch_end_callback: Callable = None, # 函数
backward_begin_callback: Callable = None,
backward_end_callback: Callable = None,
optimizer_step_begin_callback: Callable = None,
optimizer_step_end_callback: Callable = None,
forward_begin_callback: Callable = None,
forward_end_callback: Callable = None,
):
def __init__(
self,
model: nn.Module,
data_loader: Iterable,
optimizer: torch.optim.Optimizer,
batch_processor: BatchProcessorMixin,
device: Union[int, None],
model_convert_pipeline: Optional[Union[Dict, List]] = None,
resume_optimizer: bool = False,
resume_epoch_or_step: bool = False,
resume_dataloader: bool = False,
stop_by: Optional[str] = "epoch",
num_epochs: Optional[int] = None,
start_epoch: Optional[int] = 0,
num_steps: Optional[int] = None,
start_step: Optional[int] = 0,
callbacks: Optional[Sequence[Union[dict, CallbackMixin]]] = None,
train_metrics: Optional[dict] = None,
val_metrics: Optional[dict] = None,
profiler: Optional[dict] = None,
log_interval: int = 0,
compiler: Optional[Dict] = None,
):
2.5 类型别名
有时,我们需要为某种复杂类型创建一个别名,以便提高代码的可读性。
from typing import List, Tuple
Coordinates = List[Tuple[int, int]] # 类型别名,表示一组坐标点
def process_coordinates(coords: Coordinates):
for x, y in coords:
print(f"Processing coordinate: ({x}, {y})")
coords = [(1, 2), (3, 4), (5, 6)]
process_coordinates(coords)
2.6 NewType 用法
NewType 用于创建一个新的类型,它本质上与原类型相同,但是用于明确区分具有不同含义的相同基本类型。
from typing import NewType
UserId = NewType('UserId', int)
def get_user(user_id: UserId):
print(f"Fetching user with ID {user_id}")
user_id = UserId(123)
get_user(user_id)
3 总结
为什么使用类型注释?
- 可读性:类型注释可以让代码的意图更加明确。开发人员可以一眼看出一个变量或函数的预期类型。
- 静态分析:工具如 mypy 可以静态分析 Python 代码,检查类型错误,帮助及早发现潜在的 bug。
- IDE 支持:许多现代 IDE(如 VSCode、PyCharm)会利用类型注释提供代码补全、错误提示等功能。
- 文档生成:类型注释可以用来生成文档,帮助其他开发者理解代码的使用。
Python 类型注释使得代码更加清晰和易于理解,能够提高代码的质量和可维护性。通过在函数、变量、容器类型、泛型等地方使用类型注释,你可以显式地声明预期的数据类型并让工具进行类型检查,从而提前发现潜在的错误。