“:="语法和赋值表达式:什么和为什么? [英] ":=" syntax and assignment expressions: what and why?

查看:45
本文介绍了“:="语法和赋值表达式:什么和为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PEP 572 引入了赋值表达式(通俗地称为 Walrus Operator),为 Python 3.8 实现.这似乎是一个非常重要的新功能,因为它将允许在推导式和 lambda 函数中进行这种形式的赋值.

赋值表达式的语法、语义和语法规范究竟是什么?

PEP 379 关于添加赋值表达式"之前被拒绝了?

解决方案

PEP 572 包含许多细节,尤其是第一个问题.我将尝试简洁地总结/引用 PEP 中一些最重要的部分:

基本原理

在推导式中允许这种形式的赋值,例如列表推导式和禁止传统赋值的 lambda 函数.这也可以促进交互式调试,无需代码重构.

推荐的用例示例

a) 获取条件值

例如(在 Python 3 中):

command = input("> ")而命令 != 退出":打印(您输入:",命令)命令 = 输入(>")

可以变成:

<块引用>

while (command := input("> ")) != "quit":打印(您输入:",命令)

同样,来自文档:

<块引用>

在这个例子中,赋值表达式有助于避免调用 len()两次:

if (n := len(a)) >10:打印(f列表太长({n}个元素,预期<= 10)")

b) 简化列表推导式

例如:

<块引用>

stuff = [(lambda y: [y,x/y])(f(x)) for x in range(5)]

可以变成:

<块引用>

stuff = [[y := f(x), x/y] for x in range(5)]

语法和语义

<块引用>

在可以使用任意 Python 表达式的任何上下文中,都可以出现命名表达式.这是 name := expr 的形式,其中 expr 是任何有效的 Python 表达式,而 name 是一个标识符.

这种命名表达式的值与合并表达式的值相同,附加的副作用是目标被分配了该值

与常规赋值语句的区别

除了作为表达式而不是语句之外,PEP 中还提到了几个不同之处:表达式赋值从右到左,逗号周围有不同的优先级,并且不支持:

  • 多个目标
<块引用>

x = y = z = 0 # 等价:(z := (y := (x := 0)))

  • 分配不是单一名称:
<块引用>

# 无等价物a[i] = xself.rest = []

  • 可迭代的打包/解包
<块引用>

# 等价物需要额外的括号loc = x, y # 使用 (loc := (x, y))info = name, phone, *rest # 使用 (info := (name, phone, *rest))# 无等价物px, py, pz = 位置姓名、电话、电子邮件、*other_info = 联系人

  • 内联类型注释:
<块引用>

# 最接近的等价物是p: Optional[int]";作为单独的声明p: 可选 [int] = 无

  • 不支持增强分配:
<块引用>

total += tax # 等价:(total := total + tax)

PEP 572 introduces assignment expressions (colloquially known as the Walrus Operator), implemented for Python 3.8. This seems like a really substantial new feature since it will allow this form of assignment within comprehensions and lambda functions.

What exactly are the syntax, semantics, and grammar specification of assignment expressions?

Why is this new (and seemingly quite radical concept) being introduced, when a similar idea in PEP 379 on "Adding an assignment expression" was rejected before?

解决方案

PEP 572 contains many of the details, especially for the first question. I'll try to summarise/quote concisely arguably some of the most important parts of the PEP:

Rationale

Allowing this form of assignment within comprehensions, such as list comprehensions, and lambda functions where traditional assignments are forbidden. This can also facilitate interactive debugging without the need for code refactoring.

Recommended use-case examples

a) Getting conditional values

for example (in Python 3):

command = input("> ")
while command != "quit":
    print("You entered:", command)
    command = input("> ")

can become:

while (command := input("> ")) != "quit":
    print("You entered:", command)

Similarly, from the docs:

In this example, the assignment expression helps avoid calling len() twice:

if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")

b) Simplifying list comprehensions

for example:

stuff = [(lambda y: [y,x/y])(f(x)) for x in range(5)]

can become:

stuff = [[y := f(x), x/y] for x in range(5)]

Syntax and semantics

In any context where arbitrary Python expressions can be used, a named expression can appear. This is of the form name := expr where expr is any valid Python expression, and name is an identifier.

The value of such a named expression is the same as the incorporated expression, with the additional side-effect that the target is assigned that value

Differences from regular assignment statements

In addition to being an expression rather than statement, there are several differences mentioned in the PEP: expression assignments go right-to-left, have different priority around commas, and do not support:

  • Multiple targets

x = y = z = 0  # Equivalent: (z := (y := (x := 0)))

  • Assignments not to a single name:

# No equivalent
a[i] = x
self.rest = []

  • Iterable packing/unpacking

# Equivalent needs extra parentheses

loc = x, y  # Use (loc := (x, y))
info = name, phone, *rest  # Use (info := (name, phone, *rest))

# No equivalent

px, py, pz = position
name, phone, email, *other_info = contact

  • Inline type annotations:

# Closest equivalent is "p: Optional[int]" as a separate declaration
p: Optional[int] = None

  • Augmented assignment is not supported:

total += tax  # Equivalent: (total := total + tax)

这篇关于“:="语法和赋值表达式:什么和为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆