PEP 379 – 添加赋值表达式
- 作者:
- Jervis Whitley <jervisau at gmail.com>
- 状态:
- 已撤回
- 类型:
- 标准跟踪
- 创建时间:
- 2009-03-14
- Python 版本:
- 2.7, 3.2
- 历史记录:
摘要
此 PEP 向 Python 语言添加了一个新的赋值表达式,使在几乎任何地方都可以为表达式的结果赋值。新的表达式允许在首次使用时(例如,在比较中)为表达式的结果赋值。
动机和概要
Issue1714448“if something as x:” [1] 描述了一个允许在 if 语句中将表达式的结果赋值给名称的功能。它假设可以借用 as
语法来实现此目的。很多时候,我们感兴趣的不是表达式本身,而是组成表达式的某个项。为了清楚起见,类似这样的代码
if (f_result() == [1, 2, 3]) as res:
看起来非常有限,而这样的代码
if (f_result() as res) == [1, 2, 3]:
可能是我们想要的结果。
用例
请参阅结尾处的示例部分。
规范
我们提议使用新的表达式,其(名义)语法为
EXPR -> VAR
此单个表达式执行以下操作
- 评估
EXPR
的值,这是一个任意表达式; - 将结果赋值给
VAR
,一个单一的赋值目标;并且 - 将
EXPR
的结果留在栈顶 (TOS)
这里 ->
或 (RARROW
) 用于说明 EXPR
的结果被赋值给 VAR
的概念。
提议语法的转换如下
VAR = (EXPR)
(EXPR)
赋值目标可以是属性、下标或名称
f() -> name[0] # where 'name' exists previously.
f() -> name.attr # again 'name' exists prior to this expression.
f() -> name
此表达式应该可以在当前接受表达式的任何地方使用。
在使用赋值表达式时,当前在无效赋值期间引发的所有异常将继续被引发。例如,在上面的示例 1 和 2 中,如果 name
之前未定义,则会引发 NameError
,或者如果索引 0 超出范围,则会引发 IndexError
。
标准库中的示例
以下两个示例是在对标准库进行简短搜索后选择的,具体来说,这两个示例都来自 ast.py,该文件恰好在搜索时处于打开状态。
原始代码
def walk(node):
from collections import deque
todo = deque([node])
while todo:
node = todo.popleft()
todo.extend(iter_child_nodes(node))
yield node
使用赋值表达式
def walk(node):
from collections import deque
todo = deque([node])
while todo:
todo.extend(iter_child_nodes(todo.popleft() -> node))
yield node
原始代码
def get_docstring(node, clean=True):
if not isinstance(node, (FunctionDef, ClassDef, Module)):
raise TypeError("%r can't have docstrings"
% node.__class__.__name__)
if node.body and isinstance(node.body[0], Expr) and \
isinstance(node.body[0].value, Str):
if clean:
import inspect
return inspect.cleandoc(node.body[0].value.s)
return node.body[0].value.s
使用赋值表达式
def get_docstring(node, clean=True):
if not isinstance(node, (FunctionDef, ClassDef, Module)):
raise TypeError("%r can't have docstrings"
% node.__class__.__name__)
if node.body -> body and isinstance(body[0] -> elem, Expr) and \
isinstance(elem.value -> value, Str):
if clean:
import inspect
return inspect.cleandoc(value.s)
return value.s
示例
下面显示的示例突出了赋值表达式的一些期望特性以及一些可能的极端情况。
- 在 if 语句中进行赋值以供以后使用
def expensive(): import time; time.sleep(1) return 'spam' if expensive() -> res in ('spam', 'eggs'): dosomething(res)
- 在 while 循环子句中进行赋值
while len(expensive() -> res) == 4: dosomething(res)
- 保留 for 循环的迭代器对象
for ch in expensive() -> res: sell_on_internet(res)
- 极端情况
for ch -> please_dont in expensive(): pass # who would want to do this? Not I.
参考
版权
此文档已进入公有领域。
来源: https://github.com/python/peps/blob/main/peps/pep-0379.rst
最后修改时间: 2023-09-09 17:39:29 GMT