Pourquoi n'y a-t-il pas d' opérateurs ++
et --
en Python?
Pourquoi n'y a-t-il pas d' opérateurs ++
et --
en Python?
Réponses:
Ce n'est pas parce que cela n'a pas de sens; il est parfaitement logique de définir "x ++" comme "x + = 1, en évaluant la liaison précédente de x".
Si vous voulez connaître la raison d'origine, vous devrez soit parcourir les anciennes listes de diffusion Python ou demander à quelqu'un qui était là (par exemple, Guido), mais c'est assez facile à justifier après coup:
L'incrémentation et la décrémentation simples ne sont pas nécessaires autant que dans d'autres langues. Vous n'écrivez pas des choses comme for(int i = 0; i < 10; ++i)
en Python très souvent; au lieu de cela, vous faites des choses comme for i in range(0, 10)
.
Puisqu'il n'est pas nécessaire presque aussi souvent, il y a beaucoup moins de raisons de lui donner sa propre syntaxe spéciale; lorsque vous avez besoin d'augmenter, +=
c'est généralement très bien.
Ce n'est pas une décision de savoir si cela a du sens, ou si cela peut être fait - il le fait, et il le peut. Il s'agit de savoir si l'avantage vaut la peine d'être ajouté à la syntaxe de base du langage. N'oubliez pas qu'il s'agit de quatre opérateurs - postinc, postdec, preinc, predec, et chacun d'entre eux aurait besoin d'avoir ses propres surcharges de classe; ils doivent tous être spécifiés et testés; cela ajouterait des opcodes au langage (impliquant un moteur VM plus grand, et donc plus lent); chaque classe qui prend en charge un incrément logique devrait les implémenter (en plus de +=
et -=
).
Tout cela est redondant avec +=
et -=
, ce serait donc une perte nette.
i
directement - si vous en avez réellement besoin et ne pouvez pas, par exemple, utiliserarray.append()
i++
et ++i
...
++
et --
utilisé de manière à aboutir à des définitions indéfinies ou non spécifiées. comportement. Ils permettent d'écrire du code compliqué et difficile à analyser correctement.
Cette réponse originale que j'ai écrite est un mythe du folklore de l'informatique : démystifié par Dennis Ritchie comme "historiquement impossible" comme indiqué dans les lettres aux rédacteurs des Communications de l'ACM juillet 2012 doi: 10.1145 / 2209249.2209251
Les opérateurs d'incrémentation / décrémentation C ont été inventés à une époque où le compilateur C n'était pas très intelligent et les auteurs voulaient pouvoir spécifier l'intention directe qu'un opérateur en langage machine soit utilisé, ce qui permettait d'économiser une poignée de cycles pour un compilateur qui pourrait faire un
load memory
load 1
add
store memory
au lieu de
inc memory
et le PDP-11 supportait même les instructions "auto-incrémentation" et "auto-incrémentation différée" correspondant respectivement à *++p
et *p++
. Voir section 5.3 du manuel si horriblement curieux.
Comme les compilateurs sont assez intelligents pour gérer les astuces d'optimisation de haut niveau intégrées à la syntaxe de C, ils ne sont plus qu'une commodité syntaxique.
Python n'a pas d'astuces pour transmettre des intentions à l'assembleur car il n'en utilise pas.
J'ai toujours supposé que cela avait à voir avec cette ligne du zen de python:
Il devrait y avoir une - et de préférence une seule - manière évidente de le faire.
x ++ et x + = 1 font exactement la même chose, il n'y a donc aucune raison d'avoir les deux.
one--
est zéro ?
one--
est un dans la phrase, mais zéro immédiatement après. Donc, ce «koan» laisse également entendre que les opérateurs d'incrémentation / décrémentation ne sont pas évidents.
Bien sûr, nous pourrions dire "Guido vient de décider de cette façon", mais je pense que la question porte vraiment sur les raisons de cette décision. Je pense qu'il y a plusieurs raisons:
Parce que, en Python, les entiers sont immuables (int + + renvoie en fait un objet différent).
De plus, avec ++ / -, vous devez vous soucier de la pré-incrémentation et de la décroissance post-incrémentation, et cela ne prend qu'une touche de plus pour écrire x+=1
. En d'autres termes, cela évite toute confusion potentielle au détriment de très peu de gain.
42++
... Quelque chose comme ça (modifier une constante littérale) était en fait possible dans certains anciens compilateurs Fortran (ou du moins j'ai lu): Toutes les utilisations futures de ce littéral dans cette exécution de programme aurait alors vraiment une valeur différente. Bon débogage!
int
en général sont immuables. Un int
en C désigne simplement une place dans la mémoire. Et les bits à cet endroit sont très variables. Vous pouvez, par exemple, créer une référence à un int
et modifier le référent de cette référence. Cette modification est visible dans toutes les références (y compris la int
variable d' origine ) à cet endroit. Il n'en va pas de même pour un objet entier Python.
Python est beaucoup de clarté et aucun programmeur n'est susceptible de deviner correctement la signification de--a
moins qu'il / elle ait appris un langage ayant cette construction.
Python consiste également à éviter les constructions qui invitent à des erreurs et à++
opérateurs sont connus pour être de riches sources de défauts. Ces deux raisons suffisent pour ne pas avoir ces opérateurs en Python.
La décision selon laquelle Python utilise l'indentation pour marquer les blocs plutôt que des moyens syntaxiques tels qu'une certaine forme de bracketing de début / fin ou de marquage de fin obligatoire est basée en grande partie sur les mêmes considérations.
Par exemple, jetez un œil à la discussion sur l'introduction d'un opérateur conditionnel (en C cond ? resultif : resultelse
:) dans Python en 2005. Lisez au moins le premier message et le message de décision de cette discussion (qui avait précédemment plusieurs précurseurs sur le même sujet).
Anecdote: Le PEP fréquemment mentionné est le PEP 308 "Proposition d'extension Python" . LC signifie compréhension de liste , GE signifie expression de générateur (et ne vous inquiétez pas si ceux-ci vous confondent, ce ne sont pas les rares endroits compliqués de Python).
Ma compréhension de pourquoi python n'a pas d' ++
opérateur est la suivante: Lorsque vous écrivez ceci en python, a=b=c=1
vous obtiendrez trois variables (étiquettes) pointant vers le même objet (dont la valeur est 1). Vous pouvez le vérifier en utilisant la fonction id qui renverra une adresse mémoire d'objet:
In [19]: id(a)
Out[19]: 34019256
In [20]: id(b)
Out[20]: 34019256
In [21]: id(c)
Out[21]: 34019256
Les trois variables (étiquettes) pointent vers le même objet. Incrémentez maintenant une variable et voyez comment elle affecte les adresses mémoire:
In [22] a = a + 1
In [23]: id(a)
Out[23]: 34019232
In [24]: id(b)
Out[24]: 34019256
In [25]: id(c)
Out[25]: 34019256
Vous pouvez voir que cette variable a
pointe maintenant vers un autre objet en tant que variables b
et c
. Parce que vous l'avez utilisé, a = a + 1
c'est clairement clair. En d'autres termes, vous attribuez complètement un autre objet à étiqueter a
. Imaginez que vous puissiez l'écrire a++
suggérerait que vous n'avez pas assigné à un a
nouvel objet variable mais que vous avez incrémenté l'ancien. Tout cela est à mon humble avis pour minimiser la confusion. Pour une meilleure compréhension, voyez comment fonctionnent les variables python:
Python est-il appelé par valeur ou par référence? Ni.
Python passe-t-il par valeur ou par référence?
Python passe-t-il par référence ou passe-par-valeur?
Python: Comment passer une variable par référence?
Comprendre les variables Python et la gestion de la mémoire
Émulation du comportement passe-par-valeur en python
Il a juste été conçu de cette façon. Les opérateurs d'incrémentation et de décrémentation ne sont que des raccourcis pour x = x + 1
. Python a généralement adopté une stratégie de conception qui réduit le nombre de moyens alternatifs pour effectuer une opération. L'affectation augmentée est la chose la plus proche des opérateurs d'incrémentation / décrémentation en Python, et ils n'ont même pas été ajoutés avant Python 2.0.
return a[i++]
par return a[i=i+1]
.
Je suis très nouveau sur python mais je soupçonne que la raison en est à cause de l'accent mis entre les objets mutables et immuables dans le langage. Maintenant, je sais que x ++ peut facilement être interprété comme x = x + 1, mais il semble que vous incrémentez en place un objet qui pourrait être immuable.
Juste ma conjecture / sentiment / intuition.
x++
est plus proche x += 1
que de x = x + 1
, ces deux-là font également une différence sur les objets mutables.
Premièrement, Python n'est qu'indirectement influencé par C; il est fortement influencé par ABC , qui n'a apparemment pas ces opérateurs , il ne devrait donc pas être surprenant de ne pas les trouver en Python.
En second lieu , comme d' autres l' ont dit, et incrément sont pris en charge par décrément +=
et-=
déjà.
Troisièmement, un support complet pour un ++
et--
ensemble d'opérateurs inclut généralement la prise en charge des versions préfixe et postfixe de ceux-ci. En C et C ++, cela peut conduire à toutes sortes de "jolies" constructions qui semblent (à mes yeux) aller à l'encontre de l'esprit de simplicité et de franchise que Python embrasse.
Par exemple, bien que l'instruction C while(*t++ = *s++);
puisse sembler simple et élégante à un programmeur expérimenté, à quelqu'un qui l'apprend, elle est tout sauf simple. Ajoutez un mélange d'incréments et de décréments de préfixe et de postfix, et même de nombreux pros devront s'arrêter et réfléchir un peu.
Je crois que cela découle du credo de Python selon lequel "explicite vaut mieux qu'implicite".
Cela peut être dû au fait que @GlennMaynard considère la question comme en comparaison avec d'autres langages, mais en Python, vous faites les choses à la manière de python. Ce n'est pas une question «pourquoi». Il est là et vous pouvez faire les choses avec le même effet x+=
. Dans Le Zen de Python , il est dit: "il ne devrait y avoir qu'une seule façon de résoudre un problème." Les choix multiples sont grands en art (liberté d'expression) mais moche en ingénierie.
La ++
classe d'opérateurs sont des expressions avec des effets secondaires. C'est quelque chose que l'on ne trouve généralement pas en Python.
Pour la même raison, une affectation n'est pas une expression en Python, empêchant ainsi l' if (a = f(...)) { /* using a here */ }
idiome commun .
Enfin, je soupçonne qu'il n'y a pas d'opérateur très cohérent avec la sémantique de référence Pythons. N'oubliez pas que Python n'a pas de variables (ou pointeurs) avec la sémantique connue de C / C ++.
f(a)
où a
est une liste, un objet immuable.
Une meilleure question serait peut-être de se demander pourquoi ces opérateurs existent en C. K&R appelle les opérateurs d'incrémentation et de décrémentation «inhabituels» (section 2.8 page 46). L'introduction les appelle «plus concis et souvent plus efficaces». Je soupçonne que le fait que ces opérations se produisent toujours dans la manipulation de pointeurs a également joué un rôle dans leur introduction. En Python, il a probablement été décidé que cela n'avait aucun sens d'essayer d'optimiser les incréments (en fait, je viens de faire un test en C, et il semble que l'assembly généré par gcc utilise addl au lieu d'incl dans les deux cas) et il n'y a pas arithmétique du pointeur; il aurait donc été juste une façon de plus de le faire et nous savons que Python déteste cela.
comme je l'ai compris, vous ne penserez donc pas que la valeur en mémoire est modifiée. en c lorsque vous faites x ++ la valeur de x en mémoire change. mais en python tous les nombres sont immuables d'où l'adresse que x pointait comme a toujours x pas x + 1. lorsque vous écrivez x ++, vous pensez que x change ce qui se passe réellement, c'est que la réfraction x est changée en un emplacement en mémoire où x + 1 est stocké ou recrée cet emplacement si la biche n'existe pas.
++
différent de += 1
?
Pour compléter des réponses déjà bonnes sur cette page:
Supposons que nous décidions de le faire, préfixe (++i
) qui briserait les opérateurs unaires + et -.
Aujourd'hui, le préfixe de ++
ou --
ne fait rien, car il active l'opérateur unaire plus deux fois (ne fait rien) ou unaire moins deux fois (deux fois: s'annule)
>>> i=12
>>> ++i
12
>>> --i
12
Donc, cela pourrait potentiellement briser cette logique.
D'autres réponses ont expliqué pourquoi ce n'est pas nécessaire pour les itérateurs, mais parfois il est utile lors de l'affectation d'augmenter une variable en ligne, vous pouvez obtenir le même effet en utilisant des tuples et une affectation multiple:
b = ++a
devient:
a,b = (a+1,)*2
et b = a++
devient:
a,b = a+1, a
Python 3.8 introduit l' :=
opérateur d' affectation , ce qui nous permet de réaliser foo(++a)
avec
foo(a:=a+1)
foo(a++)
est toujours insaisissable.
Je pense que cela se rapporte aux concepts de mutabilité et d'immuabilité des objets. 2,3,4,5 sont immuables en python. Reportez-vous à l'image ci-dessous. 2 a fixé l'id jusqu'à ce processus python.
x ++ signifierait essentiellement un incrément sur place comme C. En C, x ++ effectue des incréments sur place. Ainsi, x = 3, et x ++ incrémenterait 3 en mémoire à 4, contrairement à python où 3 existerait toujours en mémoire.
Ainsi en python, vous n'avez pas besoin de recréer une valeur en mémoire. Cela peut conduire à des optimisations de performances.
Ceci est une réponse basée sur l'intuition.
Je sais que c'est un vieux fil, mais le cas d'utilisation le plus courant pour ++ i n'est pas couvert, c'est-à-dire l'indexation manuelle des ensembles quand il n'y a pas d'index fournis. Cette situation est la raison pour laquelle python fournit enumerate ()
Exemple: dans une langue donnée, lorsque vous utilisez une construction comme foreach pour itérer sur un ensemble - pour l'exemple, nous dirons même que c'est un ensemble non ordonné et vous avez besoin d'un index unique pour tout les différencier, par exemple
i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
uniquestuff[key] = '{0}{1}'.format(val, i)
i += 1
Dans des cas comme celui-ci, python fournit une méthode énumérée, par exemple
for i, (key, val) in enumerate(stuff.items()) :