PEP 379 – 添加赋值表达式
- 作者:
- Jervis Whitley <jervisau at gmail.com>
- 状态:
- 已撤回
- 类型:
- 标准跟踪
- 创建日期:
- 2009年3月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
最后修改: 2025-02-01 08:59:27 GMT