typing模块初探

Published: 28 Mar 2020 Category: python

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.