别院牧志知识库 别院牧志知识库
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 辨析

  • Sockets编程

  • Django

  • stackoverflow

  • Flask

  • 全栈之路

  • 面试

  • 代码片段

  • 异步编程

  • 😎Awesome资源

  • PEP

    • PEP 中文翻译计划
    • [译] PEP-8 -- 编码风格指南中文版✨✨
    • [译] PEP202--列表推导式
    • [译] PEP 255--简单的生成器
    • [译] PEP 285--添加一种布尔类型
    • [译] PEP 318--函数和方法的装饰器
    • [译] PEP 328--导入多行及绝对/相对
    • [译]pep 333 -- Python Web 服务器网关接口 v1.0
    • [译]PEP 342--增强型生成器——协程
    • [译]PEP 380--子生成器的语法
    • [译]PEP 484 -- 类型提示
    • [译] PEP 525--异步生成器
    • [译] PEP 530--异步推导式
    • [译] PEP614--放宽对装饰器的语法限制
    • [译] PEP-312--Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性
    • [译]PEP 3099--Python 3 中不会改变的事情
    • [译] PEP 3105--改 print 为函数
    • [译]PEP 3107 -- 函数注解
      • 背景
      • 函数注解的基础知识
      • 语法
        • 参数
        • 返回值
        • Lambda 表达式
      • 访问函数注解
      • 使用案例
    • [译]PEP-3129 类装饰器
    • [译] PEP 3155--类和方法的特定名称
    • [译]pep 3333 -- Python Web 服务器网关接口 v1.0.1
  • Python工匠系列

  • 高阶知识点

  • Python 学习资源待整理
  • 设计模式

  • 好“艹蛋”的 Python 呀!
  • FIFO | 待学清单📝
  • pip 安装及使用
  • 数据分析

  • 源码阅读计划

  • OOP

  • 关于 python 中的 setup.py
  • 并行分布式框架 Celery
  • 七种武器,让你的代码提高可维护性
  • 使用 pdb 调试 Python 代码
  • 每周一个 Python 标准库
  • 🐍Python
  • PEP
佚名
2019-11-27
目录

[译]PEP 3107 -- 函数注解

PEP 原文 : https://www.python.org/dev/peps/pep-3107/

PEP 标题: Function Annotations

PEP 作者: Collin Winter , Tony Lownds

创建日期: 2006-12-2

合入版本: 3.0

译者 :Robert Lu ( Blog : https://www.robberphex.com )

# 背景

Python 2.x 系列缺乏一个标准的方式来说明一个函数的参数和返回值,各种工具和库的出现填补了这一空白。一些工具使用了“PEP 318”中的装饰器,而其他的工具则去解析函数的文档注释,寻找注解。

在这一点上,众多已存在的机制和语法造成了很大的混乱。本 PEP 的目的是提供一个单一的,标准的方式指定这些信息,减少这些混乱。

# 函数注解的基础知识

在仔细讨论 Python 3.0 的函数注解的细节之前,首先让我们大致讨论下注解是什么、不是什么:

  1. 函数注解,无论是对参数的还是对返回值的函数注解,完全是可选的。

  2. 函数注解无非是一种方法,用来在编译时将任意 Python 表达式和函数的不同部分关联起来。就这点而言,Python 并没有给注解赋予特殊的意义和重要性。Python 仅仅让这些表达式可以被访问而已,以一种像本文的“访问函数注解”中描述的方法。注解对含义产生作用的唯一方式是当它们被第三方库解释的时候。这些注解的使用者可以用这些函数注解做他们想做的任何事情。例如,一个库可以利用字符串类型的注解来提供改进过的帮助信息:

    def compile(source: "something compilable",
                filename: "where the compilable thing comes from",
                mode: "is this a single statement or a suite?"):
        ...
    
    1
    2
    3
    4

    另一个库可以用来提供 Python 函数和方法的类型检查。这个库可以使用注解来说明函数的预期输入和返回值的类型:

    def haul(item: Haulable, *vargs: PackAnimal) -> Distance:
        ...
    
    1
    2

    然而,不论是第一个例子中的字符串还是第二个例子中的类型信息,它们自己没有任何含义;含义来自第三方库。

  3. 根据第二点,该 PEP 不会试图引入一种标准的语义,即使是为那些内置类型。这个工作留给第三方库。

# 语法

# 参数

对参数的注解跟随着参数名,采用了一种可选表达式的形式:

def foo(a: expression, b: expression = 5):
    ...
1
2

在伪语法中,参数现在看起来像 identifier [: expression] [= expression] 。即,注解在参数的默认值之前,而且两者都是可选的。就像等号是用来标记一个默认值的,冒号用来标记注解。像默认值一样,所有的注解表达式都会在函数定义的时候被求值。

“多余”的参数(例如:*args 和**kwargs )的注解以同样的方式标记:

def foo((x1, y1: expression),
        (x2: expression, y2: expression)=(None, None)):
    ...
1
2
3

# 返回值

到目前为止,例子都忽略了如何注解一个函数的返回值类型。方法如下:

def sum() -> expression:
    ...
1
2

即,参数列表后可以跟着字符-> 和一个 Python 表达式。像对参数的注解一样,这个表达式会在函数定义的时候被求值。

现在函数定义的语法 (opens new window)是:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: ((tfpdef ['=' test] ',')*
                ('*' [tname] (',' tname ['=' test])* [',' '**' tname]
                 | '**' tname)
                | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
tname: NAME [':' test]
tfpdef: tname | '(' tfplist ')'
tfplist: tfpdef (',' tfpdef)* [',']
1
2
3
4
5
6
7
8
9
10
11

# Lambda 表达式

lambda 的语法不支持注解。本可以通过修改 lambda 的语法来支持注解,即要求用圆括号围住参数列表。但是,已经决定 (opens new window)不进行此项更改,因为:

  1. 这将是一个不兼容的更改。
  2. 不论如何,Lambda 会被阉割。
  3. 一个 Lambda 总是可以被改为一个函数。

# 访问函数注解

一旦被编译,函数注解是可以通过函数的 func_annotations 属性来访问的。该属性是一个可变字典类型,参数名称映射到一个对象,这个对象代表求值后的注解。

return 在 func_annotations 中是一个特殊的键。只有在为函数的返回值提供了注解的情况下,return 键才会出现。

例如,如下注解:

def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
    ...
1
2

将会产生一个这样的 func_annotation 映射:

{'a': 'x',
 'b': 11,
 'c': list,
 'return': 9}
1
2
3
4

选择 return 键,是因为它不会和参数名称冲突。任何用 return 作为函数参数名的尝试都会导致语法错误(SyntaxError )

如果函数没有注解,或者函数创建自一个 lamba 表达式,则 func_annotations 是一个空的、可变的字典。

# 使用案例

在讨论注解的过程中,一些使用案例已经出现。有些在这里列出,以它们要传达的信息来分组。还包括在现有的产品和包中使用注解的例子。

  • 提供类型信息
    • 类型检查(link 1 (opens new window), link 2 (opens new window))
    • 让 IDE 显示函数期望的类型和返回的类型(link (opens new window))
    • 函数重载/泛型函数(link (opens new window))
    • 其他语言的桥[Foreign-language bridges](link 1 (opens new window), link 2 (opens new window))
    • 配接[Adaptation](link 1 (opens new window), link 2 (opens new window))
    • 逻辑谓词功能[Predicate logic functions]
    • 数据库查询映射
    • RPC 参数封装(link (opens new window))
  • 其他信息
    • 为参数和返回值的文档说明(link (opens new window))
编辑 (opens new window)
#装饰器
上次更新: 2024-07-15, 08:03:22
[译] PEP 3105--改 print 为函数
[译]PEP-3129 类装饰器

← [译] PEP 3105--改 print 为函数 [译]PEP-3129 类装饰器→

最近更新
01
提升沟通亲和力的实用策略
03-26
02
工作
07-15
03
如何选房子
06-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 IMOYAO | 别院牧志
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式