web-dev-qa-db-fra.com

Pourquoi l'affectation Python) ne renvoie pas de valeur?

Pourquoi Python assignation une instruction plutôt qu'une expression? Si c'était une expression qui renvoie la valeur du côté droit dans l'affectation, cela aurait permis un code beaucoup moins détaillé dans certains cas . Y a-t-il des problèmes que je ne vois pas?

Par exemple:

# lst is some sequence
# X is come class
x = X()
lst.append(x)

aurait pu être réécrit comme:

lst.append(x = X())

Eh bien, pour être précis, ce qui précède ne fonctionnera pas car x serait traité comme un argument de mot-clé. Mais une autre paire de parens (ou un autre symbole pour les arguments de mot-clé) aurait résolu cela.

49
max

Nombreux sont ceux qui pensent que les affectations sont des expressions, en particulier dans des langages comme Python où any value est autorisé dans une condition (pas seulement des valeurs d'un type booléen), est sujet aux erreurs. On peut supposer que Guido est/était parmi ceux qui pensent ainsi. L'erreur classique est:

if x = y: # oops! meant to say ==

La situation est aussi un peu plus compliquée dans Python qu'elle ne l'est dans un langage comme C, puisque dans Python la première affectation à une variable est aussi sa déclaration . Par exemple:

def f():
    print x

def g():
    x = h()
    print x

Dans ces deux fonctions, le "print x "font des choses différentes: l'une fait référence à la variable globale x et l'autre à la variable locale x. Les x dans g est local à cause de l'affectation. Cela pourrait être encore plus déroutant (qu'il ne l'est déjà) s'il était possible d'enterrer l'affectation dans une expression/instruction plus grande.

41
Laurence Gonsalves

La réponse du monde réel: ce n'est pas nécessaire.

La plupart des cas que vous voyez dans C sont dus au fait que la gestion des erreurs est effectuée manuellement:

if((fd = open("file", O_RDONLY)) == -1)
{
    // error handling
}

De même pour la façon dont de nombreuses boucles sont écrites:

while(i++ < 10)
    ;

Ces cas courants sont réalisés différemment en Python. La gestion des erreurs utilise généralement la gestion des exceptions; les boucles utilisent généralement des itérateurs.

Les arguments contre cela ne sont pas nécessairement bouleversants, mais ils sont mis en balance avec le fait que ce n'est tout simplement pas si important en Python.

15
Glenn Maynard

Vous pouvez vous attendre à une assistance pour (x := y) expressions à implémenter dans une prochaine version de python. Guido a récemment accepté une proposition, PEP 572 en juillet 2018, pour prendre en charge les expressions d'affectation en python. (Il y avait également eu des propositions antérieures à ce sujet, telles que le retrait PEP 379 .)

Rappelez-vous que jusqu'à la version 3, print était aussi une instruction plutôt qu'une expression.

Remarque: L'instruction x = y = z pour attribuer la même valeur à plusieurs cibles (ou plutôt, plusieurs listes de cibles , puisque le déballage est également autorisé) était déjà supporté depuis longtemps en python, mais implémenté comme une syntaxe spéciale plutôt qu'en enchaînant des sous-expressions d'affectation successives. (En effet, l'ordre dans lequel les affectations individuelles sont effectuées est inversé.)

8
benjimin

Je crois que c'était délibéré de la part de Guido afin d'éviter certaines erreurs classiques. Par exemple.

if x = 3: print x

quand tu voulais vraiment dire

if x == 3: ...

Je suis d'accord qu'il y a des moments où j'aurais souhaité que cela fonctionne, mais { et } autour d'un bloc de code, et cela ne va certainement pas changer.

7
Peter Rowell
  1. La syntaxe de Python est beaucoup moins verbeuse que la syntaxe de C.
  2. Il a des règles de portée beaucoup plus sophistiquées que C.
  3. Utiliser des parenthèses dans chaque expression réduit la lisibilité du code et python évite cela.

Si les affectations étaient des expressions, ces fonctionnalités et bien d'autres devraient être retravaillées. Pour moi, c'est comme un accord que vous devez conclure pour avoir un code lisible et des fonctionnalités utiles. Dans le but d'avoir

if a and (h not in b): ...

plutôt que

if (a && !(h in b)) { ... }

[ne parle pas du genre d'erreur classique (si a = b :).]

4
FRD