Dass zwei Fragen dieselbe Antwort haben, bedeutet nicht, dass es sich um Duplikate handelt. Trivial, um sich selbst zu antworten, aber nicht trivial, um die Argumentation zu sehen, oder ob es einen Ausweg gibt.
Mehmet
Antworten:
107
Warum probieren Sie es nicht aus?
>>>def some_func():...return2...>>> a =2>>>if(a = some_func()):File"<stdin>", line 1if(a = some_func()):^SyntaxError: invalid syntax
>>>
Dies ist absichtlich verboten, da Guido, der wohlwollende Python-Diktator, sie für unnötig und eher verwirrend als nützlich hält. Es ist der gleiche Grund, warum es keine Post-Inkrement- oder Pre-Inkrement-Operatoren (++) gibt.
Matt Boehm
4
er hat die Zugabe von erlauben Augmented assigment in 2,0 weil x = x + 1erfordert zusätzliche Lookup - Zeit , während x += 1etwas schneller war, aber ich bin sicher , hat er nicht einmal , wie zu tun , dass viel. :-)
wescpy
hoffe, das wird bald möglich. Python entwickelt sich nur langsam
Nik O'Lai
54
UPDATE - Die ursprüngliche Antwort befindet sich ganz unten
Zusammenfassung
Dies ist ein Vorschlag zum Erstellen einer Möglichkeit zum Zuweisen von Variablen innerhalb eines Ausdrucks unter Verwendung der Notation NAME: = Ausdruck. Eine neue Ausnahme, TargetScopeError, wurde hinzugefügt, und die Auswertungsreihenfolge wurde geändert.
Das "PEP 572-Durcheinander" war das Thema einer Sitzung des Python Language Summit 2018, die von dem wohlwollenden Diktator für das Leben (BDFL) Guido van Rossum geleitet wurde. PEP 572 versucht, der Sprache Zuweisungsausdrücke (oder "Inline-Zuweisungen") hinzuzufügen, hat jedoch eine längere Diskussion über mehrere große Threads auf der Python-Dev-Mailingliste gesehen - selbst nach mehreren Runden mit Python-Ideen. Diese Threads waren oft umstritten und eindeutig so umfangreich, dass viele sie wahrscheinlich gerade ausgeschaltet haben. Auf dem Gipfel gab Van Rossum einen Überblick über den Feature-Vorschlag, den er offenbar gerne annimmt, wollte aber auch diskutieren, wie diese Art von Fadenexplosion in Zukunft vermieden werden kann.
if reductor := dispatch_table.get(cls):
rv = reductor(x)elif reductor := getattr(x,"__reduce_ex__",None):
rv = reductor(4)elif reductor := getattr(x,"__reduce__",None):
rv = reductor()else:raiseError("un(deep)copyable object of type %s"% cls)
datetime.py
tz wird nur für s + = tz verwendet, wobei die Zuordnung innerhalb des if verschoben wird, um den Umfang anzuzeigen.
Aktuell:
s = _format_time(self._hour, self._minute,
self._second, self._microsecond,
timespec)
tz = self._tzstr()if tz:
s += tz
return s
Verbessert:
s = _format_time(self._hour, self._minute,
self._second, self._microsecond,
timespec)if tz := self._tzstr():
s += tz
return s
sysconfig.py Wenn Sie fp.readline () in der while-Bedingung aufrufen und .match () in den if-Zeilen aufrufen, wird der Code ohne kompakter
macht es schwieriger zu verstehen.
Aktuell:
whileTrue:
line = fp.readline()ifnot line:break
m = define_rx.match(line)if m:
n, v = m.group(1,2)try:
v = int(v)exceptValueError:pass
vars[n]= v
else:
m = undef_rx.match(line)if m:
vars[m.group(1)]=0
Verbessert:
while line := fp.readline():if m := define_rx.match(line):
n, v = m.group(1,2)try:
v = int(v)exceptValueError:pass
vars[n]= v
elif m := undef_rx.match(line):
vars[m.group(1)]=0
Vereinfachen des Listenverständnisses Ein Listenverständnis kann effizient erfasst und gefiltert werden, indem die Bedingung erfasst wird:
results =[(x, y, x/y)for x in input_data if(y := f(x))>0]
Ebenso kann ein Unterausdruck innerhalb des Hauptausdrucks wiederverwendet werden, indem ihm bei der ersten Verwendung ein Name gegeben wird:
stuff =[[y := f(x), x/y]for x in range(5)]
Beachten Sie, dass in beiden Fällen die Variable y im enthaltenden Bereich gebunden ist (dh auf derselben Ebene wie Ergebnisse oder Material).
Erfassen von Bedingungswerten Zuweisungsausdrücke können im Header einer if- oder while-Anweisung effektiv verwendet werden:
# Loop-and-a-halfwhile(command := input("> "))!="quit":print("You entered:", command)# Capturing regular expression match objects# See, for instance, Lib/pydoc.py, which uses a multiline spelling# of this effectif match := re.search(pat, text):print("Found:", match.group(0))# The same syntax chains nicely into 'elif' statements, unlike the# equivalent using assignment statements.elif match := re.search(otherpat, text):print("Alternate found:", match.group(0))elif match := re.search(third, text):print("Fallback found:", match.group(0))# Reading socket data until an empty string is returnedwhile data := sock.recv(8192):print("Received data:", data)
Insbesondere bei der while-Schleife kann dies die Notwendigkeit einer Endlosschleife, einer Zuweisung und einer Bedingung beseitigen. Es wird auch eine glatte Parallele zwischen einer Schleife erstellt, die einfach einen Funktionsaufruf als Bedingung verwendet, und einer Schleife, die diesen als Bedingung verwendet, aber auch den tatsächlichen Wert verwendet.
Gabel Ein Beispiel aus der UNIX-Welt auf niedriger Ebene:
if pid := os.fork():# Parent codeelse:# Child code
Beachten Sie, dass in Python im Gegensatz zu C die Zuweisung nicht innerhalb von Ausdrücken erfolgen kann. C-Programmierer mögen darüber meckern, aber es vermeidet eine häufige Klasse von Problemen, die in C-Programmen auftreten: Geben Sie = in einen Ausdruck ein, wenn == beabsichtigt war.
Ich mag diese Antwort, weil sie tatsächlich darauf hinweist, warum ein solches "Feature" in Python absichtlich weggelassen wurde. Beim Unterrichten von Anfängerprogrammen habe ich viele gesehen, die diesen Fehler gemacht haben, if (foo = 'bar')als sie beabsichtigten, den Wert von zu testen foo.
Jonathan Cross
2
@ JonathanCross, Diese "Funktion" wird tatsächlich in 3.8 hinzugefügt. Es ist unwahrscheinlich, dass es so sparsam eingesetzt wird, wie es sollte - aber zumindest ist es keine Ebene=
John La Rooy
@JohnLaRooy: Wenn ich mir die Beispiele anschaue, denke ich, dass "es unwahrscheinlich ist, dass sie so sparsam eingesetzt werden, wie es sollte", genau richtig war. Von den ~ 10 Beispielen finde ich, dass nur zwei den Code tatsächlich verbessern. (Als einziger Ausdruck entweder in einer Weile, um zu vermeiden, dass die Linie dupliziert wird oder die Schleifenbedingung im Körper vorliegt, oder in einer Elifkette, um ein Verschachteln zu vermeiden)
Aleksi Torhamo,
39
Nein, die BDFL mochte diese Funktion nicht.
Von meinem Platz aus hat Guido van Rossum, "Wohlwollender Diktator fürs Leben", hart dafür gekämpft, Python so einfach wie möglich zu halten. Wir können uns mit einigen seiner Entscheidungen streiten - ich hätte es vorgezogen, wenn er "Nein" gesagt hätte Aber die Tatsache, dass es kein Komitee gab, das Python entwarf, sondern einen vertrauenswürdigen "Beirat", der größtenteils auf Verdiensten basiert und die Sensibilität eines Designers filtert, hat meiner Meinung nach eine verdammt schöne Sprache hervorgebracht, IMHO.
Einfach? Diese Funktion könnte einen Teil meines Codes vereinfachen, da sie ihn kompakter und daher lesbarer hätte machen können. Jetzt brauche ich zwei Zeilen, wo ich früher eine brauchte. Ich habe nie verstanden, warum Python Funktionen abgelehnt hat, die andere Programmiersprachen seit vielen Jahren haben (und oft aus einem sehr guten Grund). Besonders diese Funktion, über die wir hier sprechen, ist sehr, sehr nützlich.
Regis
6
Weniger Code ist nicht immer einfacher oder besser lesbar. Nehmen Sie zum Beispiel eine rekursive Funktion. Das Loop-Äquivalent ist oft besser lesbar.
FMF
1
Ich mag die C-Version nicht, aber ich vermisse es wirklich, etwas wie Rost zu haben, if letwenn ich eine If-Elif-Kette habe, aber ich muss den Wert der Bedingung in jedem Fall speichern und verwenden.
Thayne
1
Ich muss sagen, dass der Code, den ich gerade schreibe (der Grund, warum ich dieses Problem gesucht habe), ohne diese Funktion VIEL hässlicher ist. Anstatt if zu verwenden, gefolgt von vielen anderen ifs, muss ich das nächste if unter dem letzten else einrücken.
MikeKulls
16
Nicht direkt nach diesem alten Rezept von mir - aber wie das Rezept sagt, ist es einfach, das semantische Äquivalent zu erstellen, z. B. wenn Sie direkt von einem C-codierten Referenzalgorithmus transliterieren müssen (natürlich vor dem Refactoring zu mehr idiomatischem Python; -). Dh:
classDataHolder(object):def __init__(self, value=None): self.value = value
def set(self, value): self.value = value;return value
def get(self):return self.value
data =DataHolder()while data.set(somefunc()):
a = data.get()# use a
Übrigens, eine sehr idiomatische pythonische Form für Ihren speziellen Fall, wenn Sie genau wissen, welcher falsche Wert zurückkehren somefunckann, wenn er einen falschen Wert zurückgibt (z. B. 0)
for a in iter(somefunc,0):# use a
in diesem speziellen Fall wäre das Refactoring also ziemlich einfach ;-).
Wenn die Rückkehr könnte jede Art von falsish Wert (0, None, '', ...), eine Möglichkeit ist:
import itertools
for a in itertools.takewhile(lambda x: x, iter(somefunc, object())):# use a
Möglicherweise bevorzugen Sie jedoch einen einfachen benutzerdefinierten Generator:
def getwhile(func,*a,**k):whileTrue:
x = func(*a,**k)ifnot x:breakyield x
for a in getwhile(somefunc):# use a
Ich würde das zweimal abstimmen, wenn ich könnte. Dies ist eine großartige Lösung für Zeiten, in denen so etwas wirklich benötigt wird. Ich habe Ihre Lösung an eine Regex-Matcher-Klasse angepasst, die einmal instanziiert wird. Anschließend wird .check () in der if-Anweisung und .result () in ihrem Text verwendet, um die Übereinstimmung abzurufen, falls vorhanden. Vielen Dank! :)
Teekin
15
Ja, aber nur ab Python 3.8.
PEP 572 schlägt Zuweisungsausdrücke vor und wurde bereits akzeptiert.
# Handle a matched regexif(match := pattern.search(data))isnotNone:# Do something with match# A loop that can't be trivially rewritten using 2-arg iter()while chunk := file.read(8192):
process(chunk)# Reuse a value that's expensive to compute[y := f(x), y**2, y**3]# Share a subexpression between a comprehension filter clause and its output
filtered_data =[y for x in data if(y := f(x))isnotNone]
@ MarkRansom Alle begrüßen Guido. Richtig ... seufz.
Javadba
@javadba der Typ hat viel öfter recht gehabt als er sich geirrt hat. Ich schätze, dass eine einzige Person, die für die Vision verantwortlich ist, zu einer viel kohärenteren Strategie führt als die Gestaltung durch das Komitee. Ich kann mit C ++ vergleichen und kontrastieren, das mein Hauptbrot und Butter ist.
Mark Ransom
Ich fühle, dass sowohl Ruby als auch Scala (in verschiedenen Sprachen) es deutlich besser machen als Python: aber auf jeden Fall ist hier nicht der
richtige
4
Dank der neuen Funktion von Python 3.8 wird es möglich sein, so etwas ab dieser Version zu tun, obwohl nicht der =Ada-ähnliche Zuweisungsoperator verwendet wird :=. Beispiel aus den Dokumenten:
# Handle a matched regexif(match := pattern.search(data))isnotNone:# Do something with match
Einer der Gründe, warum Zuweisungen unter bestimmten Bedingungen illegal sind, besteht darin, dass es einfacher ist, einen Fehler zu machen und Richtig oder Falsch zuzuweisen:
some_variable =5# This does not work# if True = some_variable:# do_something()# This only works in Python 2.xTrue= some_variable
printTrue# returns 5
In Python 3 sind Wahr und Falsch Schlüsselwörter, also kein Risiko mehr.
Antworten:
Warum probieren Sie es nicht aus?
Also nein.
Update: Dies ist (mit unterschiedlicher Syntax) in Python 3.8 möglich
quelle
x = x + 1
erfordert zusätzliche Lookup - Zeit , währendx += 1
etwas schneller war, aber ich bin sicher , hat er nicht einmal , wie zu tun , dass viel. :-)UPDATE - Die ursprüngliche Antwort befindet sich ganz unten
Python 3.8 bringt PEP572
https://lwn.net/Articles/757713/
https://www.python.org/dev/peps/pep-0572/#examples-from-the-python-standard-library
Ursprüngliche Antwort
http://docs.python.org/tutorial/datastructures.html
siehe auch:
http://effbot.org/pyfaq/why-can-ti-use-an-assignment-in-an-expression.htm
quelle
if (foo = 'bar')
als sie beabsichtigten, den Wert von zu testenfoo
.=
Nein, die BDFL mochte diese Funktion nicht.
Von meinem Platz aus hat Guido van Rossum, "Wohlwollender Diktator fürs Leben", hart dafür gekämpft, Python so einfach wie möglich zu halten. Wir können uns mit einigen seiner Entscheidungen streiten - ich hätte es vorgezogen, wenn er "Nein" gesagt hätte Aber die Tatsache, dass es kein Komitee gab, das Python entwarf, sondern einen vertrauenswürdigen "Beirat", der größtenteils auf Verdiensten basiert und die Sensibilität eines Designers filtert, hat meiner Meinung nach eine verdammt schöne Sprache hervorgebracht, IMHO.
quelle
if let
wenn ich eine If-Elif-Kette habe, aber ich muss den Wert der Bedingung in jedem Fall speichern und verwenden.Nicht direkt nach diesem alten Rezept von mir - aber wie das Rezept sagt, ist es einfach, das semantische Äquivalent zu erstellen, z. B. wenn Sie direkt von einem C-codierten Referenzalgorithmus transliterieren müssen (natürlich vor dem Refactoring zu mehr idiomatischem Python; -). Dh:
Übrigens, eine sehr idiomatische pythonische Form für Ihren speziellen Fall, wenn Sie genau wissen, welcher falsche Wert zurückkehren
somefunc
kann, wenn er einen falschen Wert zurückgibt (z. B.0
)in diesem speziellen Fall wäre das Refactoring also ziemlich einfach ;-).
Wenn die Rückkehr könnte jede Art von falsish Wert (0,
None
,''
, ...), eine Möglichkeit ist:Möglicherweise bevorzugen Sie jedoch einen einfachen benutzerdefinierten Generator:
quelle
Ja, aber nur ab Python 3.8.
PEP 572 schlägt Zuweisungsausdrücke vor und wurde bereits akzeptiert.
Zitieren des Syntax- und Semantikteils des PEP:
In Ihrem speziellen Fall können Sie schreiben
quelle
Die Zuweisung in Python ist eine Anweisung, kein Ausdruck.
quelle
Dank der neuen Funktion von Python 3.8 wird es möglich sein, so etwas ab dieser Version zu tun, obwohl nicht der
=
Ada-ähnliche Zuweisungsoperator verwendet wird:=
. Beispiel aus den Dokumenten:quelle
Sie können eine Funktion definieren, die die Zuweisung für Sie übernimmt:
quelle
Einer der Gründe, warum Zuweisungen unter bestimmten Bedingungen illegal sind, besteht darin, dass es einfacher ist, einen Fehler zu machen und Richtig oder Falsch zuzuweisen:
In Python 3 sind Wahr und Falsch Schlüsselwörter, also kein Risiko mehr.
quelle
== True
sowieso auf die richtige Seite gehen.Der Zuweisungsoperator - auch informell als Walrossoperator bezeichnet - wurde am 28. Februar 2018 in PEP572 erstellt .
Der Vollständigkeit halber werde ich die relevanten Teile veröffentlichen, damit Sie die Unterschiede zwischen 3.7 und 3.8 vergleichen können:
quelle