文章详情页 您现在的位置是:网站首页>文章详情

真香!python静态类型注释

图片丢失 Jeyrce.Lu 发表于:2020年7月23日 20:08 分类:【Python 2693次阅读

python是一门动态类型语言,变量无需定义类型,这在某些地方被称作python灵活的优点,但是随着业务的迭代,你会发现这种优点也许就是语言本身的缺点。

为什么需要静态类型注释

def run(user, group):
    u = user.create("xxx")
    group.add(user)

比如这样一个函数,你这样写没有任何问题,IDE检查不出来任何错误,代码看起来简短优雅,但实际上你可能遇到过这些困扰:

(1)你根本不知道user对象是否有create方法可以调用,你也不知道group对象是否有add方法可以给你调用,直到运行时解释器才会traceback。

(2)你在编写这段代码时,你打出一个user.然后table补全,编辑器没有办法联想出来能为你补全什么。

(3)当这个项目足够大、足够抽象时,你可能需要里三层外三层查看代码,最后终于能够确定user和group到底是什么类型。

简单类型注释

也许是很多开发者都遇到了这样的困扰,python团队终于在语言层面下手了,python3.6中引入了静态类型注解,虽然他只是注解并不能强制规定一个变量的类型,但是这已经足够解决以上三个问题了。

def do_something(name: str, age: int, children: list) -> (str, tuple):
    print(name, age, children)
    return "xx", (1,)

以上代码定义了一个函数,他接收一个str类型的参数、一个int类型的参数、一个list类型的参数,返回一个str类型的值和一个tuple类型的值;此时我们在函数提使用变量.table进行自动补全时IDE已经可以联想出我们可能想调用的方法了,如果调用了一个不存在的方法则会进行warn提示,函数被调用时如果传递的参数或返回值和声明不对应也会进行warn提示。

更加全面的类型注释——typing

以上例子只进行了一个简单的类型注释,如果我们想要对list和tuple中子元素的类型做更进一步的声明,就需要引入类型注解住专用的包typing了。以下对常用的类型注解进行举例:

(1)声明一个子元素为str类型的list参数(个数不限)

# 导入类型声明,以下代码段均省略
from typing import *


def process_items(items: List[str]) -> NoReturn:
    for item in items:
        print(item)

(2)声明一个拥有2个子元素的tuple,且元素类型分别为int和str

def tuple_(items: Tuple[int, str]):
    pass

(3)声明一个key为str类型,value为float类型的dict

def shop(item: Dict[str, float]):
    for k, v in item.items():
        print(k, v)

(4)声明一个自定义类User类型的参数,返回值为任意字符串

class User(object):
    def __init__(self, name: AnyStr, age: Optional[int] = 0):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)

    def do(self):
        pass


def say(user: User) -> AnyStr:
    return user.name

(5)声明一个任意类型参数(和不声名一样)

def any_(x: Any):
    pass

(6)声明一个可选参数类型,类型可以是str或float或int

def union(x: Union[int, float, str]):
    print(x)

(7)声明一个子元素类型为int,长度不限的tuple类型

x: Tuple[int, ...] = 1, 2, 3

(8)声明一个可执行类型f,且f接收一个str类型和一个int类型参数,返回一个float类型的值

def run(x: str, y: int, f: Callable[[str, int], float]) -> float:
    return f(x, y)

(9)声明一个可执行类型f,f返回值为int类型,参数无要求

def call(f: Callable[..., int]):
    f()

(10)声明一个可变参数且设置默认值

def f(x: Optional[int] = None) -> Optional[int]:
    return x

(11)为类型声明起一个别名(这在类型声明很长时、类型声明需要重复引用时非常好用)

X = Union[Tuple[str, int, List[float], Dict[str, AnyStr]], Dict[str, float]]


def f__() -> X:
    return {"y": 77}

(12)声明一个数据类型,类似于data_class装饰器

PointY = NamedTuple('PointY', [('x', str), ('y', int)])


class PointX(NamedTuple):
    x: str
    y: int

用过了静态类型注释之后,我只想说“真香!”。

版权声明 本文属于本站  原创作品,文章版权归本站及作者所有,请尊重作者的创作成果,转载、引用自觉附上本文永久地址: http://blog.lujianxin.com/x/art/r6brlot01v21

文章评论区

作者名片

图片丢失
  • 作者昵称:Jeyrce.Lu
  • 原创文章:61篇
  • 转载文章:3篇
  • 加入本站:1838天

站点信息

  • 运行天数:1839天
  • 累计访问:164169人次
  • 今日访问:0人次
  • 原创文章:69篇
  • 转载文章:4篇
  • 微信公众号:第一时间获取更新信息