Python靜態類型


Mypy是Python的可選靜態類型檢查器。您可以在Python程序中添加類型提示(PEP 484),並使用mypy進行靜態類型檢查。查找程序中的錯誤,甚至不運行它們!

安裝Mypy

Mypy需要運行Python 3.5或更高版本。下面代碼是用的Python 3.7 使用pip安裝mypy:

$ python3 -m pip install mypy

 

看幾個簡單例子:
平時我們代碼大概都是下面的樣子:

# 參數name的類型是未知的
# 返回的類型也是未知的
def greeting(name):
    return 'Hello ' + name

稍微修改一些

# 參數name后面跟了:str 代表name期望是str類型
# 參數括號后面跟了->str代表返回類型為str類型
def greeting(name: str) -> str:
    return 'Hello ' + name
x: str = 'xxx' # 聲明一個變量為str類型
greeting(x) # Hello xxx
greeting(123) # TypeError: can only concatenate str (not "int") to str

到目前為止僅有str、float等基本類型,使用list、tuple復雜類型需要引用typing中的類

 

LIST

數組類型

from typing import List

# 參數names為list類型並且元素都是str類型
# 返回為None
def greet_all(names: List[str]) -> None:
    for name in names:
        print('Hello ' + name)

names = ["Alice", "Bob", "Charlie"]
ages = [10, 20, 30]

greet_all(names)   # Ok!
greet_all(ages)    #出錯了 Error due to incompatible types 

 

Dict

字典類型

from typing import Dict

# Dict[int, str] int代表key類型, str代表val類型
def test(t: Dict[int, str]) -> Dict:
    return t

test({1: '234'}) # {1: '234'}

 

Iterable

可以迭代類型包括 List、Set、Tuple、Str、Dict

def greeting(names: Iterable[str]) -> None:
    for name in names:
        print(name)

greeting(['aaa', 'bbb']) # list aaa bbb
greeting(('ccc', 'ddd')) # tuple ccc ddd
greeting({'eee', 'fff'}) # set eee fff
greeting({'ggg': 'hhh'}) # dict ggg
greeting('123') # str 1 2 3 
greeting(678) # error: Argument 1 to "greeting" has incompatible type "int"; expected "Iterable[str]"

 

Union

接受多個指定類型,但不接受除此外的類型

from typing import Union
# user_id 只能為int或者str
def normalize_id(user_id: Union[int, str]) -> str:
    if isinstance(user_id, int):
        return 'user-{}'.format(100000 + user_id)
    else:
        return user_id
normalize_id(1) # user-100001
normalize_id('2') # 2

 

Optional

可選類型,給參數設置默認值

from typing import Optional

# Optional[str]只是Union [str,None]的簡寫或別名。它主要是為了方便幫助功能簽名看起來更清潔
# Optional[str, int] 只能包含一個類型, 這樣是不正確的
def greeting(name: Optional[str] = None) -> str:
    if name is None:
        name = 'stranger'
    return 'Hello, ' + name
greeting() # Hello, stranger
greeting('123') # Hello, 123

 

Any

有時候我們不確定是什么類型的時候可以用到Any

from typing import Any

def greeting(name: Any = None) -> str:
    if name is None:
        name = 'stranger'

    return 'Hello, ' + str(name)

greeting() # Hello, stranger
greeting('123') # Hello, 123
greeting(234) # Hello, 234
greeting([345]) # Hello, [345]

 

TypeVar

自定義類型

from typing import TypeVar

T = TypeVar('T') # 任意類型
A = TypeVar('A', int, str) # A類型只能為int或str
def test(t: A) -> None:
    print(t)
test(1)

 

Type comments

No first-class syntax support for explicitly marking variables as being of a specific type is added by this PEP(pep-0484). To help with type inference in complex cases, a comment of the following format may be used:

x = []                # type: List[Employee]
x, y, z = [], [], []  # type: List[int], List[int], List[str]
x, y, z = [], [], []  # type: (List[int], List[int], List[str])
a, b, *c = range(5)   # type: float, float, List[float]
x = [1, 2]            # type: List[int]

Type comments should be put on the last line of the statement that contains the variable definition. They can also be placed on with statements and for statements, right after the colon.

Examples of type comments on with and for statements:

with frobnicate() as foo:  # type: int
    # Here foo is an int
    ...

for x, y in points:  # type: float, float
    # Here x and y are floats
    ...

In stubs it may be useful to declare the existence of a variable without giving it an initial value. This can be done using PEP 526 variable annotation syntax:

from typing import IO

stream: IO[str]    # Note: no initial value!

 

參考鏈接: 

https://www.jianshu.com/p/37f945cd91c3

官方鏈接:

https://docs.python.org/3.6/library/typing.html#distinct

https://www.python.org/dev/peps/pep-0484/

https://www.python.org/dev/peps/pep-0585/

 

相關問題鏈接:

https://stackoverflow.com/questions/43982085/mypy-error-incompatible-type-despite-using-union

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM