web-dev-qa-db-fra.com

": =" syntaxe et expressions d'affectation: quoi et pourquoi?

PEP 572 introduit des expressions d'affectation (familièrement connu sous le nom de Walrus Operator ), implémenté pour Python = 3.8 Cela semble être une nouvelle fonctionnalité vraiment substantielle car elle permettra cette forme d'affectation dans les fonctions de compréhension et lambda.

Quelles sont exactement la syntaxe, la sémantique et la grammaire des expressions d'affectation?

Pourquoi ce nouveau concept (et apparemment assez radical) est-il introduit alors qu'une idée similaire dans PEP 379 sur "Ajouter une expression d'affectation" a été rejetée auparavant?

29
Chris_Rands

PEP 572 contient de nombreux détails, en particulier pour la première question. Je vais essayer de résumer/citer de manière concise sans doute certaines des parties les plus importantes du PEP:

Justification

Autoriser cette forme d'affectation dans les compréhensions, telles que les compréhensions de liste et les fonctions lambda où les affectations traditionnelles sont interdites. Cela peut également faciliter le débogage interactif sans avoir besoin de refactorisation de code.

Syntaxe et sémantique

Dans n'importe quel contexte où des expressions arbitraires Python peuvent être utilisées, une expression nommée peut apparaître. Il s'agit de la forme name := exprexpr est une expression Python et nom est un identifiant valide).

La valeur d'une telle expression nommée est la même que l'expression incorporée, avec l'effet secondaire supplémentaire que la cible se voit attribuer cette valeur

Différences par rapport aux instructions d'affectation régulières

En plus d'être une expression plutôt qu'une instruction, il existe plusieurs différences mentionnées dans le PEP: les affectations d'expression vont de droite à gauche, ont une priorité différente autour des virgules et ne prennent pas en charge:

  • Plusieurs cibles
x = y = z = 0  # Equivalent: (z := (y := (x := 0)))
  • Affectations non à un seul nom:
# No equivalent
a[i] = x
self.rest = []
  • Emballage/déballage itérable
# 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
  • Annotations de type en ligne:
# Closest equivalent is "p: Optional[int]" as a separate declaration
p: Optional[int] = None
  • L'affectation augmentée n'est pas prise en charge:
total += tax  # Equivalent: (total := total + tax)

Cas d'utilisation recommandés

a) Simplifier la compréhension des listes

par exemple:

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

peut devenir:

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

b) Obtention de valeurs conditionnelles

par exemple (dans Python 3):

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

peut devenir:

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

Quelques exemples de mes exemples préférés où les expressions d'affectation peuvent rendre le code plus concis et plus facile à lire:

if instruction

Avant:

match = pattern.match(line)
if match:
    return match.group(1)

Après:

if match := pattern.match(line):
    return match.group(1)

Instruction infinie while

Avant:

while True:
    data = f.read(1024)
    if not data:
        break
    use(data)

Après:

while data := f.read(1024):
    use(data)

Il y a autres bons exemples dans le PEP .

14