# ===== CodeLab: python-typing =====
# 以下代码片段按文章出现顺序拼接, 共 8 段

# ----- 片段 1 (python) -----
# 没有注解:你能猜出 price 是什么类型吗?
def total(items, price):
    return len(items) * price

# 加上注解:签名本身就是文档
def total(items: list, price: float) -> float:
    return len(items) * price

# ----- 片段 2 (python) -----
name: str = "CodeLab"
age: int = 3

def greet(name: str, times: int = 1) -> str:
    return f"{name}! " * times

print(greet("你好"))     # 你好!
print(greet("嗨", 2))    # 嗨! 嗨!
print(greet.__annotations__)

# ----- 片段 3 (python) -----
from typing import Dict, List, Optional, Union

def find_user(users: Dict[str, int], name: str) -> Optional[int]:
    return users.get(name)

def parse_number(value: Union[int, str]) -> int:
    if isinstance(value, str):
        return int(value)
    return value

print(find_user({"alice": 1, "bob": 2}, "bob"))   # 2
print(parse_number("42"))                          # 42

# ----- 片段 4 (python) -----
from typing import Callable, TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

def apply(func: Callable[[int], int], x: int) -> int:
    return func(x)

print(first([10, 20, 30]))          # 10
print(first(["a", "b", "c"]))       # a
print(apply(lambda n: n + 100, 1))  # 101

# ----- 片段 5 (bash) -----
pip install mypy
mypy app.py

# ----- 片段 6 (python) -----
def add(a: int, b: int) -> int:
    return a + b

# 故意传字符串:mypy 会警告,运行时照样能跑
print(add("1", "2"))

# ----- 片段 7 (python) -----
# 旧代码暂时不想动,先用注释跳过 mypy 检查
value: str = "hello"  # type: ignore

def show(v: str) -> None:
    print(v)

show(value)

# ----- 片段 8 (text) -----
[tool.mypy]
python_version = "3.11"
strict = true          # 开启严格模式,所有函数都要求注解
