typing模块初探
python3支持类型提示,来看一些常见写法的demo。
# https://docs.python.org/3/library/typing.html
# https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
# build in types
from typing import List, Set, Dict, Tuple, Optional
# For simple built-in types, just use the name of the type
x: int = 1
x: float = 1.0
x: bool = True
x: str = "test"
x: bytes = b"test"
# For collections, type is capitalized, name of the type inside the collection is in brackets
x: List[int] = [1]
x: Set[int] = {6, 7}
# For mappings, we need the types of both keys and values
x: Dict[str, float] = {'field': 2.0}
# For tuples of fixed size, we specify the types of all the elements
x: Tuple[int, str, float] = (3, "yes", 7.5)
# For tuples of variable size, we use one type and ellipsis
x: Tuple[int, ...] = (1, 2, 3)
# Use Optional[] for values that could be None
def some_function(n):
if n > 1:
return "OK"
else:
return None
x: Optional[str] = some_function(0)
# Functions
from typing import Callable, Iterator, Union, Optional, List
# This is how you annotate a function definition
def stringify(num: int) -> str:
return str(num)
# And here's how you specify multiple arguments
def plus(num1: int, num2: int) -> int:
return num1 + num2
# Add default value for an argument after the type annotation
def f(num1: int, my_float: float = 3.5) -> float:
return num1 + my_float
# This is how you annotate a callable (function) value
x: Callable[[int, float], float] = f
# A generator function that yields ints is secretly just a function that
# returns an iterator of ints, so that's how we annotate it
def g(n: int) -> Iterator[int]:
i = 0
while i < n:
yield i
i += 1
from typing import Union, Any, List, Optional, cast
# Use Union when something could be one of a few types
x: List[Union[int, str]] = [3, 5, "test", "fun"]
# Use Any if you don't know the type of something or it's too dynamic to write a type for
def mystery_function():
pass
x: Any = mystery_function()
# If you initialize a variable with an empty container or "None"
x: List[str] = []
x: Optional[str] = None
# This makes each positional arg and each keyword arg a "str"
def call(self, *args: str, **kwargs: str) -> str:
request = make_request(*args, **kwargs)
return self.do_api_query(request)
# Standard duck types
from typing import Mapping, MutableMapping, Sequence, Iterable, List, Set
# Use Iterable for generic iterables (anything usable in "for"),
# and Sequence where a sequence (supporting "len" and "__getitem__") is
# required
def f(ints: Iterable[int]) -> List[str]:
return [str(x) for x in ints]
f(range(1, 3))
# Mapping describes a dict-like object (with "__getitem__") that we won't
# mutate, and MutableMapping one (with "__setitem__") that we might
def f(my_mapping: Mapping[int, str]) -> List[int]:
my_mapping[5] = 'maybe' # if we try this, mypy will throw an error...
return list(my_mapping.keys())
f({3: 'yes', 4: 'no'})
def f(my_mapping: MutableMapping[int, str]) -> Set[str]:
my_mapping[5] = 'maybe' # ...but mypy is OK with this.
return set(my_mapping.values())
f({3: 'yes', 4: 'no'})
# Type aliases. A type alias is defined by assigning the type to the alias.
from typing import List
Vector = List[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
new_vector = scale(2.0, [1.0, -4.2, 5.4]) # a list of floats qualifies as a Vector.