Python類型註解與typing的使用(轉)

轉自:https://liaolei.cc/?p=99

衆所周知, Python是一種動態語言 在聲明一個變量時我們不需要顯示的聲明它的類型.

類型註釋可以提高代碼的可讀性和易用性, 幫助開發者寫出更加嚴謹的代碼, 讓調用者減少類型方面的錯誤, 但是, 類型註解語法傳入的類型表述有限, 不能說明覆雜的類型組成情況, 因此引入了typing模塊, 用來實現複雜的類型表述

一、類型註解

1.具體語法

  • 在聲明變量類型時,變量後方緊跟一個冒號,冒號後面跟一個空格,再跟上變量的類型.
  • 在聲明方法返回值的時候,箭頭左邊是方法定義,箭頭右邊是返回值的類型,箭頭左右兩邊都要留有空格.
a: int = 2
def add(a: int) -> int:
    pass

二、typing

類型檢查,防止運行時出現參數、返回值類型不符。

作爲開發文檔附加說明,方便使用者調用時傳入和返回參數類型。

模塊加入不會影響程序的運行不會報正式的錯誤,pycharm支持typing檢查錯誤時會出現黃色警告。

1.基礎用法

from typing import List, Tuple, Dict

names: List[str] = ["li", "tom"]
version: Tuple[int, int, int] = (6, 6, 6)
operations: Dict[str, bool] = {'sad': False, 'happy': True}
Python

2.類型

TypeDescription
int 整型
float 浮點數字
bool 布爾
str 字符串
bytes 8位字符
object 任意對象
List(str) 字符串組成的列表
Tuple[int, ...] 任意數量的int對象的元組
Tuple[int, int] 兩個int對象的元組
Dict[str, int] 鍵是 str 值是 int 的字典
Iterable[int] 包含 int 的可迭代對象
Sequence[bool] 布爾值序列(只讀)
Mapping[str, int] 從 str 鍵到 int 值的映射(只讀)
Any 具有任意類型的動態類型值
Union 聯合類型
Optional 參數可以爲空或已經聲明的類型
Mapping 映射,是 collections.abc.Mapping 的泛型
MutableMapping Mapping 對象的子類,可變
Generator 生成器類型, Generator[YieldType、SendType、ReturnType]
NoReturn 函數沒有返回結果
Set 集合 set 的泛型, 推薦用於註解返回類型
AbstractSet collections.abc.Set 的泛型,推薦用於註解參數
Sequence ollections.abc.Sequence 的泛型,list、tuple 等的泛化類型
TypeVar 自定義兼容特定類型的變量
NewType 聲明一些具有特殊含義的類型
Callable 可調用類型, Callable[[參數類型], 返回類型]

List

var: List[int or float] = [2, 3.5]
var: List[List[int]] = [[1, 2], [2, 3]]
Python

Tuple

person: Tuple[str, int, float] = ('Mike', 22, 1.75)
Python

Dict、Mapping、MutableMapping

Dict、字典,是 dict 的泛型;Mapping,映射,是 collections.abc.Mapping 的泛型。

  • Dict 推薦用於註解返回類型
  • Mapping 推薦用於註解參數
  • MutableMapping 則是 Mapping 對象的子類,在很多庫中也經常用 MutableMapping 來代替 Mapping。
def size(rect: Mapping[str, int]) -> Dict[str, int]:
    return {'width': rect['width'] + 100, 'height': rect['width'] + 100}
Python

Set、AbstractSet

  • Set 推薦用於註解返回類型
  • AbstractSet 用於註解參數
def describe(s: AbstractSet[int]) -> Set[int]:
    return set(s)
Python

Sequence

在某些情況下,我們可能並不需要嚴格區分一個變量或參數到底是列表 list 類型還是元組 tuple 類型,我們可以使用一個更爲泛化的類型,叫做 Sequence,其用法類似於 List

def square(elements: Sequence[float]) -> List[float]:
    return [x ** 2 for x in elements]
Python

NoReturn

當一個方法沒有返回結果時,爲了註解它的返回類型,我們可以將其註解爲 NoReturn

def hello() -> NoReturn:
    print('hello')
Python

Any

一種特殊的類型,它可以代表所有類型,靜態類型檢查器的所有類型都與 Any 類型兼容,所有的無參數類型註解和返回類型註解的都會默認使用 Any 類型

def add(a: Any) -> Any:
    return a + 1
Python

TypeVar

自定義兼容特定類型的變量

height = 1.75
Height = TypeVar('Height', int, float, None)
def get_height() -> Height:
    return height
Python

NewType

聲明一些具有特殊含義的類型

Person = NewType('Person', Tuple[str, int, float])
person = Person(('Mike', 22, 1.75))
Python

Callable

可調用類型,它通常用來註解一個方法

def date(year: int, month: int, day: int) -> str:
    return f'{year}-{month}-{day}'
# 參數類型和返回值類型都要註解出來
def get_date_fn() -> Callable[[int, int, int], str]:
    return date
Python

lambda類型標註

is_even: Callable[[int], bool] = lambda x: (x % 2 == 0)
Python

Union

聯合類型,Union[X, Y] 代表要麼是 X 類型,要麼是 Y 類型。 聯合類型的聯合類型等價於展平後的類型

Union[Union[int, str], float] == Union[int, str, float]
Union[int] == int
Union[int, str, int] == Union[int, str]
Union[int, str] == Union[str, int]
Python
def process(: Union[str, Callable]):
     isinstance(, str):
        # str2fn and process
        pass
     isinstance(, Callable):
        ()
Python

Optional

參數可以爲空或已經聲明的類型, 即 Optional[X] 等價於 Union[X, None]

不等價於可選參數,當它作爲參數類型註解的時候,不代表這個參數可以不傳遞了,而是說這個參數可以傳爲 None

# 當一個方法執行結果, 如果執行完畢就不返回錯誤信息, 如果發生問題就返回錯誤信息
def judge(result: bool) -> Optional[str]:
    if result: return 'Error Occurred'
Python

Generator

生成器類型, 聲明方式, 其後的中括號緊跟着三個參數,分別代表 YieldType、SendType、ReturnType

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'
Python
  • YieldType: yield 關鍵字後面緊跟的變量的類型
  • SendType: yield 返回的結果的類型就是 SendType, 可爲None
  • ReturnType: 最後生成器 return 的內容類型, 可爲None

三、實例

代碼來源於 requests-html

# Typing.
_Find = Union[List['Element'], 'Element']
_XPath = Union[List[str], List['Element'], str, 'Element']
_Result = Union[List['Result'], 'Result']
_HTML = Union[str, bytes]
_BaseHTML = str
_UserAgent = str
_DefaultEncoding = str
_URL = str
_RawHTML = bytes
_Encoding = str
_LXML = HtmlElement
_Text = str
_Search = Result
_Containing = Union[str, List[str]]
_Links = Set[str]
_Attrs = MutableMapping
_Next = Union['HTML', List[str]]
_NextSymbol = List[str]


class Element(BaseParser):
    """An element of HTML.

    :param element: The element from which to base the parsing upon.
    :param url: The URL from which the HTML originated, used for ``absolute_links``.
    :param default_encoding: Which encoding to default to.
    """

    __slots__ = [
        'element', 'url', 'skip_anchors', 'default_encoding', '_encoding',
        '_html', '_lxml', '_pq', '_attrs', 'session'
    ]

    def __init__(self, *, element, url: _URL, default_encoding: _DefaultEncoding = None) -> None:
        super(Element, self).__init__(element=element, url=url, default_encoding=default_encoding)
        self.element = element
        self.tag = element.tag
        self.lineno = element.sourceline
        self._attrs = None

    def __repr__(self) -> str:
        attrs = ['{}={}'.format(attr, repr(self.attrs[attr])) for attr in self.attrs]
        return "<Element {} {}>".format(repr(self.element.tag), ' '.join(attrs))

    @property
    def attrs(self) -> _Attrs:
        """Returns a dictionary of the attributes of the :class:`Element <Element>`
        (`learn more <https://www.w3schools.com/tags/ref_attributes.asp>`_).
        """
        if self._attrs is None:
            self._attrs = {k: v for k, v in self.element.items()}

            # Split class and rel up, as there are usually many of them:
            for attr in ['class', 'rel']:
                if attr in self._attrs:
                    self._attrs[attr] = tuple(self._attrs[attr].split())

        return self._attrs

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章