zoukankan      html  css  js  c++  java
  • python

    转自 Python -类型提示 Type Hints - 小菠萝测试笔记 - 博客园 (cnblogs.com)

    为什么会有类型提示

    • Python是一种动态类型语言,这意味着我们在编写代码的时候更为自由,运行时不需要指定变量类型
    • 但是与此同时 IDE 无法像静态类型语言那样分析代码,及时给我们相应的提示,比如字符串的 split 方法
    def split_str(s):
        strs = s.split(",")
    

    由于不知道参数 s 是什么类型,所以当你敲 s. 的时候不会出现 split 的语法提示

    常用类型提示

    typing 是在 python 3.5 才有的模块

    常用类型提示

    • int,long,float : 整型,长整形,浮点型;
    • bool,str : 布尔型,字符串类型;
    • List, Tuple, Dict, Set :列表,元组,字典, 集合;
    • Iterable,Iterator :可迭代类型,迭代器类型;
    • Generator:生成器类型;

    前两行小写的不需要 import,后面三行都需要通过 typing 模块 import 哦

    例子

    指定函数参数类型

    单个参数

    # name 参数类型为 str 
    def greeting(name: str) :    
    	return "hello"
    

    多个参数

    # 多个参数,参数类型均不同 
    def add(a: int, string: str, f: float, b: bool or str):
    	print(a, string, f, b)
    

    bool or str:代表参数 b 可以是布尔类型,也可以是字符串

    指定函数返回的参数类型

    # 函数返回值指定为字符串 
    def greeting(name: str) -> str:
    	return "hello"
    

    复杂一点的栗子

    from typing import Tuple, List, Dict
    
    # 返回一个 Tuple 类型的数据,第一个元素是 List,第二个元素是 Tuple,第三个元素是 Dict,第四个元素可以是字符串或布尔
    def add(a: int, string: str, f: float, b: bool or str) -> Tuple[List, Tuple, Dict, str or bool]:
        list1 = list(range(a))
        tup = (string, string, string)
        d = {"a": f}
        bl = b
        return list1, tup, d, bl
    
    
    # 不 warn 的调用写法
    print(add(1, "2", 123, True))
    
    
    # 输出结果
    ([0], ('2', '2', '2'), {'a': 123}, True)
    

    那指定类型的时候用 list、set、dict、tuple 可不可以呢?

    可以是可以,但是不能指定里面元素数据类型

    def test(a: list, b: dict, c: set, d: tuple):
        print(a, b, c, d)
    

    List[T]、Set[T]

    只能传一个类型,传多个会报错

    a: List[int, str] = [12,"34"]
    b: Set[int, str] = {12,"23"}
    
    print(a)
    print(b)
    

    换成

    a: List[int] = [12,"34"]
    b: Set[int] = {12,"23"}
    
    print(a)
    print(b)
    

    Dict[T,T]

    e: Dict[str, int] = {"as": 123, "643": 34}
    print(e)
    

    Tuple[T]

    可以传入多个

    d: Tuple[int, str] = (1, "2")
    print(d)
    
    
    # 输出结果
    (1, '2')
    

    只写一个int,但是赋值两个int

    from typing import Tuple, List, Dict, Set
    
    d: Tuple[int, str] = (1)
    print(d)
    

    只写一个 int,赋值两个 int 元素会报 warning

    写了两个int,但是赋值多于两个

    d: Tuple[int, str] = (1, "2", "2") 
    

    不会报错,但是也会有 warning

    指定一个类型,对所有元素生效

    d: Tuple[int, ...] = (1, 2, 3)
    d: Tuple[Dict[str, str], ...] = ({"name": "poloyy"}, {"age": "33"})
    

    类型别名

    可以将复杂一点类型给个别名,这样好用一些

    变量例子

    # 别名
    vector = List[float]
    
    var: vector = [1.1, 2.2]
    # 等价写法
    var: List[float] = [1.1, 2.2]
    

    函数例子

    # float 组成的列表别名
    vector_list_es = List[float]
    # 字典别名
    vector_dict = Dict[str, vector_list_es]
    # 字典组成列表别名
    vector_list = List[vector_dict]
    
    # vector_list 等价写法,不用别名的话,有点像套娃
    vector = List[Dict[str, List[float]]]
    
    # 函数
    def scale(scalar: float, vector: vector_list) -> vector_list:
        for item in vector:
            for key, value in item.items():
                item[key] = [scalar * num for num in value]
        print(vector)
        return vector
    
    
    scale(2.2, [{"a": [1, 2, 3]}, {"b": [4, 5, 6]}])
    
    
    # 输出结果
    [{'a': [2.2, 4.4, 6.6000000000000005]}, {'b': [8.8, 11.0, 13.200000000000001]}]
    

    NewType

    可以自定义创一个新类型

    • 主要用于类型检查
    • NewType(name, tp) 返回一个函数,这个函数返回其原本的值
    • 静态类型检查器会将新类型看作是原始类型的一个子类
    • tp 就是原始类型
    from typing import NewType
    
    UserId = NewType('UserId123', int)
    
    
    def name_by_id(user_id: UserId) -> str:
        print(user_id)
        return str(user_id)
    
    
    UserId('user')  # Fails type check
    num = UserId(5)  # type: int
    
    name_by_id(42)  # Fails type check
    name_by_id(UserId(42))  # OK
    
    print(type(UserId(5)))
    

    可以看到 UserId 其实也是 int 类型

    Callable

    是一个可调用对象类型

    查看对象是否可调用

    # 返回True或False
    isinstance(对象, Callable) 
    

    例子

    # 最简单的函数
    def print_name(name: str):
        print(name)
    
    # 判断函数是否可调用
    print(isinstance(print_name, Callable))
    
    x = 1
    print(isinstance(x, Callable))
    
    # 输出结果
    True
    False
    

    函数是可调用的,所以是 True,而变量不是可调用对象,所以是 False

    Callable 作为函数返回值

    # Callable  作为函数返回值使用,其实只是做一个类型检查的作用,看看返回值是否为可调用对象
    from typing import NewType,Callable
    
    def print_name(name: str):
        print(name)
        
    def get_name_return() -> Callable[[str], None]:
        return print_name
    
    
    vars = get_name_return()
    vars("test")
    
    
    # 等价写法,相当于直接返回一个函数对象
    def get_name_test():
        return print_name
    
    
    vars2 = get_name_test()
    vars2("test")
    

    TypeVar 泛型

    任意类型

    # 可以是任意类型
    T = TypeVar('T')
    
    
    def test(name: T) -> T:
        print(name)
        return name
    
    
    test(11)
    test("aa")
    
    
    # 输出结果
    11
    aa
    

    指定类型

    # 可以是 int,也可以是 str 类型
    AA = TypeVar('AA', int, str)
    
    num1: AA = 1
    num2: AA = "123"
    print(num1, num2)
    
    num3: AA = []
    
    
    # 输出结果
    1 123
    

    Any Type

    • 一种特殊的类型是 Any
    • 静态类型检查器会将每种类型都视为与 Any 兼容,将 Any 视为与每种类型兼容
    # Any
    from typing import Any
    
    a = None  # type: Any
    a1 = []  # OK
    a2 = 2  # OK
    
    s = ''  # type: str
    s1 = a  # OK
    
    
    def foo(item: Any) -> int:
        # Typechecks; 'item' 可以是任意类型
        print(item)
        return 1
    
    
    foo(a)
    foo(a1)
    foo(a2)
    foo(s)
    foo(s1)
    

    隐式使用 Any

    def legacy_parser(text):
        ...
        return data
    
    # 上述写法等价于下述写法
    # 所有没有返回类型或参数类型的函数将隐式默认使用 Any
    def legacy_parser(text: Any) -> Any:
        ...
        return data
    

    Union

    联合类型

    Union[int, str] 表示既可以是 int,也可以是 str

    from typing import Union
    
    # vars 变量可以是int也可以是 str 类型
    vars: Union[int,str]
    vars = 1
    print(vars)
    
    vars = "123"
    print(vars)
    
    # 赋值列表会有warning
    vars = []
    print(vars)
    

    等价写法

    vars: Union[int, str]
    # 等价于
    vars: [int or str]
    
    
    vars: Union[int]
    # 等价于
    vars: int
    

    union 等价写法

    Union[int] == int 
    
    # 最终 Union[int] 返回的也是 int 类型
    
    Union[int, str, int] == Union[int, str]
    # 重复的类型参数会自动忽略掉
    
    Union[int, str] == Union[str, int]
    # 自动忽略类型参数顺序
    
    Union[Union[int, str], float] == Union[int, str, float]
    # union 嵌套 union 会自动解包
    

    Optional

    可选类型

    和默认参数有什么不一样

    • 官方原话:可选参数具有默认值,具有默认值的可选参数不需要在其类型批注上使用 Optional,因为它是可选的
    • 不过 Optional 和默认参数其实没啥实质上的区别,只是写法不同
    • 使用 Optional 是为了让 IDE 识别到该参数有一个类型提示,可以传指定的类型和 None,且参数是可选非必传的
    # 可选参数
    def foo(arg: int = 0) -> None:
        ...
    
    # 不传 arg 默认取 0
    foo()
    
    • Optional[int] 等价于 Union[int, None]
    • 意味着:既可以传指定的类型 int,也可以传 None

    例子

    使用 Optional

    def foo_func(arg: Optional[int] = None):
        print(arg)
    
    
    foo_func()
    foo_func(1)
    
    
    # 输出结果
    None
    1
    

    使用默认参数的写法

    def foo_func(arg: int = None):
        print(arg)
    
    
    foo_func()
    foo_func(1)
    
    
    # 输出结果
    None
    1
    

    这种写法,Pycharm 并不会 warning

    重点

    Optional[] 里面只能写一个数据类型

    # 正确
    Optional[str]
    Optional[List[str]]
    Optional[Dict[str, Any]]
    
    # 错误
    Optional[str, int]
    Optional[Union[str, int, float]]
    
  • 相关阅读:
    iOS图片拉伸技巧
    Swift和OC混合使用
    【转】动态计算UITableViewCell高度详解
    AutoLayout~Label
    【转】初探 iOS8 中的 Size Class
    Objective-C runtime~
    [转]Objective-C中的类和对象(instance)
    Masonry~
    [转] ios学习--openURL的使用方法
    Autolayout~代码实现
  • 原文地址:https://www.cnblogs.com/dongye95/p/15427512.html
Copyright © 2011-2022 走看看