953 votes

Comportement des opérateurs d'incrémentation et de décrémentation en Python

Comment utiliser les opérateurs de pré-incrémentation/décrémentation (++, --), tout comme en C++ ?

Pourquoi ++count s'exécute-t-il, mais ne modifie pas la valeur de la variable ?

1 votes

Chris: Tu as répondu à ma question (le quoi). De plus, j'aimerais savoir pourquoi Python diffère dans ce comportement par rapport à C/C++.

24 votes

Python n'est pas C ou C++. Différentes décisions de conception ont été prises pour créer ce langage. En particulier, Python ne définit délibérément pas d'opérateurs d'attribution pouvant être utilisés dans une expression arbitraire; plutôt, il existe des instructions d'attribution et des instructions d'attribution augmentée. Voir la référence ci-dessous.

10 votes

Qu'est-ce qui vous a fait penser que python avait des opérateurs ++ et -- ?

1239voto

Chris Lutz Points 34157

++ n'est pas un opérateur. C'est deux opérateurs +. L'opérateur + est l'opérateur d'identité, qui ne fait rien. (Clarification : les opérateurs unaires + et - ne fonctionnent que sur les nombres, mais je présume que vous ne vous attendriez pas à ce qu'un éventuel opérateur ++ fonctionne sur les chaînes de caractères.)

++count

Se traduit par

+(+count)

Ce qui se traduit par

count

Vous devez utiliser l'opérateur légèrement plus long += pour faire ce que vous voulez faire :

count += 1

Je soupçonne que les opérateurs ++ et -- ont été omis pour des raisons de cohérence et de simplicité. Je ne connais pas l'argument exact de Guido van Rossum pour cette décision, mais je peux imaginer quelques arguments :

  • Une analyse syntaxique plus simple. Techniquement, l'analyse de ++count est ambiguë, car cela pourrait être +, +, count (deux opérateurs + unaires) tout aussi bien que ce pourrait être ++, count (un opérateur unaire ++). Ce n'est pas une ambiguïté syntaxique significative, mais elle existe.
  • Langage plus simple. ++ n'est rien de plus qu'un synonyme de += 1. C'était une abréviation inventée parce que les compilateurs C étaient stupides et ne savaient pas comment optimiser a += 1 en l'instruction inc que la plupart des ordinateurs possèdent. De nos jours, avec les compilateurs optimiseurs et les langages interprétés en bytecode, l'ajout d'opérateurs à un langage pour permettre aux programmeurs d'optimiser leur code est généralement mal vu, surtout dans un langage comme Python qui est conçu pour être cohérent et lisible.
  • Effets secondaires confus. Une erreur courante des débutants dans les langages avec des opérateurs ++ est de confondre les différences (à la fois de priorité et de valeur de retour) entre les opérateurs d'incrémentation/décrémentation préfixes et postfixes, et Python aime éliminer les "pièges" du langage. Les problèmes de priorité des pré-/post-incrémentation en C sont assez complexes et très faciles à rater.

15 votes

"L'opérateur + est l'opérateur « identité », qui ne fait rien." Seulement pour les types numériques ; pour les autres types, c'est une erreur par défaut.

4 votes

D'accord. Mais encore une fois, ++ et -- ne devraient fonctionner que sur les types numériques.

47 votes

Aussi, sachez que, en Python, += et ses équivalents ne sont pas des opérateurs pouvant être utilisés dans les expressions. En Python, ils sont plutôt définis comme faisant partie d'une "instruction d'assignation augmentée". Cela est cohérent avec la décision de conception du langage en Python de ne pas autoriser l'assignation ("=") en tant qu'opérateur au sein d'expressions arbitraires, contrairement à ce qui est possible en C. Voir docs.python.org/reference/…

421voto

Lennart Regebro Points 52510

Python n'a pas d'opérateurs d'incrémentation pré et post.

En Python, les entiers sont immuables. C'est-à-dire que vous ne pouvez pas les modifier. Cela est dû au fait que les objets entiers peuvent être utilisés sous plusieurs noms. Essayez ceci :

>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True

Les variables a et b ci-dessus sont en fait le même objet. Si vous incrémentiez a, vous incrémenteriez aussi b. Ce n'est pas ce que vous voulez. Vous devez donc réaffecter. Comme ceci :

b = b + 1

Beaucoup de programmeurs en C qui ont utilisé Python ont voulu un opérateur d'incrémentation, mais cet opérateur aurait l'aspect d'incrémenter l'objet, alors qu'en réalité il le réaffecte. C'est pourquoi les opérateurs -= et += ont été ajoutés, pour être plus courts que b = b + 1, tout en étant plus clairs et plus flexibles que b++, donc la plupart des gens vont incrémenter avec :

b += 1

Ce qui réaffectera b à b+1. Ce n'est pas un opérateur d'incrémentation, car il n'incrémente pas b, il le réaffecte.

En résumé : Python se comporte différemment ici, car ce n'est pas du C, et ce n'est pas une enveloppe de bas niveau autour du code machine, mais un langage dynamique de haut niveau, où les incréments n'ont pas de sens, et ne sont pas aussi nécessaires que en C, où vous les utilisez à chaque fois que vous avez une boucle, par exemple.

87 votes

Cet exemple est faux (et vous confondez probablement l'immuabilité avec l'identité) - ils ont le même id en raison d'une optimisation du VM qui utilise les mêmes objets pour les nombres jusqu'à 255 (ou quelque chose comme ça). Par exemple (des nombres plus grands):
>>> a = 1231231231231
>>> b = 1231231231231
>>> id(a), id(b)
(32171144, 32171168)

57 votes

L'allégation d'immuabilité est fallacieuse. Conceptuellement, i++ signifierait assigner i + 1 à la variable i. i = 5; i++ signifie assigner 6 à i, et non modifier l'objet int pointé par i. Autrement dit, cela ne signifie pas incrémenter la valeur de 5!

3 votes

@Escargot mécanique : Dans ce cas, il ne s'agirait pas du tout d'opérateurs d'incrémentation. Et puis l'opérateur += est plus clair, plus explicite, plus flexible et fait de toute façon la même chose.

56voto

glglgl Points 35668

Alors que les autres réponses sont correctes en ce sens qu'elles montrent ce que signifie habituellement un simple + (à savoir, laisser le nombre tel quel, s'il s'agit d'un nombre), elles sont incomplètes en ce sens qu'elles n'expliquent pas ce qui se passe.

Pour être exact, +x évalue à x.__pos__() et ++x à x.__pos__().__pos__().

Je pourrais imaginer une structure de classe TRÈS étrange (Enfants, ne faites pas ça à la maison!) comme ceci :

class ValueKeeper(object):
    def __init__(self, value): self.value = value
    def __str__(self): return str(self.value)

class A(ValueKeeper):
    def __pos__(self):
        print('appel de A.__pos__')
        return B(self.value - 3)

class B(ValueKeeper):
    def __pos__(self):
        print('appel de B.__pos__')
        return A(self.value + 19)

x = A(430)
print(x, type(x))
print(+x, type(+x))
print(++x, type(++x))
print(+++x, type(+++x))

12voto

Vitalii Fedorenko Points 17469

En Python, une distinction entre expressions et déclarations est rigoureusement appliquée, contrairement à des langages tels que Common Lisp, Scheme, ou Ruby.

Wikipedia

Donc en introduisant de tels opérateurs, vous violeriez la distinction entre expression et déclaration.

Pour la même raison, vous ne pouvez pas écrire

if x = 0:
  y = 1

comme vous le feriez dans d'autres langages où une telle distinction n'est pas conservée.

0 votes

Intéressant, cette restriction sera levée dans la prochaine version de Python 3.8 avec la nouvelle syntaxe pour les expressions d'assignation (PEP-572 python.org/dev/peps/pep-0572). Nous pourrons écrire if (n := len(a)) > 10: y = n + 1 par exemple. Notez que la distinction est claire en raison de l'introduction d'un nouvel opérateur à cet effet (:=)

2voto

user2246134 Points 21

Un commentaire plutôt qu'une réponse.

... mais je présume que vous ne vous attendriez pas à ce qu'un opérateur hypothétique ++ fonctionne sur des chaînes.)...

Dans au moins un langage, cela fonctionne.

perl -e '$a="ascf23"; print ++$a, "\n";'
ascf24

perl -e '$a="ascf29"; print ++$a, "\n";'
ascf30

perl -e '$a="ascfaa"; print ++$a, "\n";'
ascfab

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X