Type hints最大的好处就是易于代码维护。当新成员加入,想要贡献代码时,能减小不少时间。
也方便咱们在调用汉书时提供了错误的类型传递致使运行时错误的检测。html
咱们使用一个简单例子,两个整数相加。python
def add(a, b): return a + b
上面的例子,可工做于任意能够进行+操做符的对象。若是咱们仅让该函数只能对整型做为参数,而后也只是返回整型结果呢?express
def add(a: int, b: int) -> int: return a + b
咱们注意到,返回类型是在函数定义末尾使用 -> 符号来指明。函数
Mypy是为Python构建的静态类型检查器。若是咱们使用上面的类型注解,mypy能够在代码中
帮咱们找到一些错误。你可使用在开发流程中任意阶段使用它,好比是在CI中做适当的测试。学习
咱们在虚拟环境中安装mypy测试
$ pip install mypy
咱们会进行以下示例描述,虽然代码做用不大,可是咱们能够经过它来学习类型注解以及mypy.code
class Student: def __init__(self, name, batch, branch, roll): self.name = name self.batch = batch self.branch = branch self.roll = roll self.semester = None self.papers = {} def is_passed(self): "To find if the student has pass the exam in the current semester" for k, v in self.papers.items(): if v < 34: return False return True def total_score(self): "Returns the total score of the student" total = 0 for k, v in self.papers.items(): total += v return total std1 = Student("Kushal", 2005, "cse", "123") std2 = Student("Sayan", 2005, "cse", 121) std3 = Student("Anwesha", 2005, "law", 122) std1.papers = {"english": 78, "math": 82, "science": 77} std2.papers = {"english": 80, "math": 92, "science": "78"} std3.papers = {"english": 82, "math": 87, "science": 77} for std in [std1, std2, std3]: print("Passed: {0}. The toral score of {1} is {2}".format(std.is_passed(), std.name, std.total_score()))
你可能发现了代码中其实有错误,可是在实际开发过程咱们常常会发生,而且除了在运行时发现,咱们并无其余更好的机制。orm
咱们经过mypy来执行咱们的代码,咱们把文件取名为students2.pyhtm
咱们将会在__init__方法中加入一些类型注解。为减小代码长度,修改以下:对象
class Student: def __init__(self, name: str, batch: int, branch: str, roll: int) -> None: self.name = name self.batch = batch self.branch = branch self.roll = roll self.semester = None self.papers = {} $ mypy students2.py students2.py:9: error: Need type annotation for 'papers' students2.py:29: error: Argument 4 to "Student" has incompatible type "str"; expected "int"
能够看到mypy有提示哪些变量没有类型注解,还有在29行,参数咱们指望的是整型,但在调用时传递了字符串类型,如今让咱们来修正他。
from typing import Dict class Student: def __init__(self, name: str, batch: int, branch: str, roll: int) -> None: self.name = name self.batch = batch self.branch = branch self.roll = roll self.semester = None self.papers: Dict[str, int] = {} def is_passed(self): "To find if the student has pass the exam in the current semester" for k, v in self.papers.items(): if v < 34: return False return True def total_score(self): "Returns the total score of the student" total = 0 for k, v in self.papers.items(): total += v return total std1: Student = Student("Kushal", 2005, "cse", 123) std2: Student = Student("Sayan", 2005, "cse", 121) std3: Student = Student("Anwesha", 2005, "law", 122) std1.papers = {"english": 78, "math": 82, "science": 77} std2.papers = {"english": 80, "math": 92, "science": 78} std3.papers = {"english": 82, "math": 87, "science": 77} for std in [std1, std2, std3]: print("Passed: {0}. The toral score of {1} is {2}".format(std.is_passed(), std.name, std.total_score()))
如今,没有任何错误了。在第一行咱们还从typing包引入了Dcit。并做为了self.paper的类型注解,这里的意思就是该变量是字典类型,使用字符串做为键,整型做为值。咱们设置std1, std2和std3变量注解为Student类。
如今,咱们给papers变量赋一些错误类型的值。
std1.papers = ["English", "Math"]
或者错误的字典键值对
std2.papers = {1: "Engish", 2: "Math"}
咱们能看到相似以下错误
$ mypy students2.py students2.py:35: error: Incompatible types in assignment (expression has type List[str], variable has type Dict[str, int]) students2.py:36: error: Dict entry 0 has incompatible type "int": "str" students2.py:36: error: Dict entry 1 has incompatible type "int": "str"
from typing import List, Tuple, Sequence, Optional values: List[int] = [] city: int = 350 # The city code, not a name # This function returns a Tuple of two values, a str and an int def get_details() -> Tuple[str, int]: return "Python", 5 # The following is an example of Tuple unpacking name: str marks: int name, marks = get_details() def print_all(values: Sequence) -> None: for v in values: print(v) print_all([1,2,3]) print_all({"name": "kushal", "class": 5}) # alltypes.py:23: error: Argument 1 to "print_all" has incompatible type Dict[str, object]; expected Sequence[Any] # But running the code will give us no error with wrong output def add_ten(number: Optional[int] = None) -> int: if number: return number + 10 else: return 42 print(add_ten()) print(add_ten(12))