wake-up-neo.com

Eleganter Weg, mehrere Variablen gleichzeitig zu deklarieren

Um mehrere Variablen gleichzeitig zu deklarieren, würde ich Folgendes tun:

a, b = True, False

Wenn ich jedoch viel mehr Variablen deklarieren musste, wird das immer weniger elegant:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True

Gibt es eine bessere/elegante/bequemere Möglichkeit, dies zu tun?

Danke im Voraus!

Bearbeiten:

Das muss sehr einfach sein, aber wenn ich eine Liste oder ein Tuple zum Speichern der Variablen verwende, wie müsste ich mich dann so nähern, dass ich hilfreich bin, da

aList = [a,b]

Ist nicht gültig, ich müsste tun:

a, b = True, True

Oder was fehlt mir?

109
Trufa

Wie andere vorgeschlagen haben, ist es unwahrscheinlich, dass die Verwendung von 10 verschiedenen lokalen Variablen mit Booleschen Werten der beste Weg ist, Ihre Routine zu schreiben (insbesondere, wenn sie wirklich Ein-Buchstaben-Namen haben :)

Je nachdem, was Sie gerade tun, kann es sinnvoll sein, stattdessen ein Wörterbuch zu verwenden. Wenn Sie beispielsweise Boolesche Vorgabewerte für einen Satz von Ein-Buchstaben-Flags einrichten möchten, können Sie dies tun:

>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Wenn Sie möchten, können Sie dies auch mit einer einzelnen Zuweisungsanweisung tun:

>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
...              **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Der zweite Parameter von dictist nicht vollständig dafür vorgesehen: Er soll Ihnen das Überschreiben einzelner Elemente des Wörterbuchs mithilfe von Schlüsselwortargumenten wie d=False ermöglichen. Der obige Code zerlegt das Ergebnis des Ausdrucks nach ** in eine Reihe von Schlüsselwortargumenten , die an die aufgerufene Funktion übergeben werden. Dies ist sicherlich ein zuverlässiger Weg, Wörterbücher zu erstellen, und die Leute scheinen diese Redewendung zumindest zu akzeptieren, aber ich vermute, dass einige sie für unpythonisch halten. </disclaimer>


Ein weiterer Ansatz, der wahrscheinlich am intuitivsten ist, wenn Sie dieses Muster häufig verwenden, besteht darin, Ihre Daten als eine Liste von Flag-Werten (Truename__, Falsename__) zu definieren, die Flag-Namen zugeordnet sind (Zeichenfolgen aus einem Zeichen). Anschließend transformieren Sie diese Datendefinition in ein invertiertes Wörterbuch, das Flag-Namen den Flag-Werten zuordnet. Dies kann mit einem verschachtelten Listenverständnis recht prägnant durchgeführt werden, aber hier ist eine sehr lesbare Implementierung:

>>> def invert_dict(inverted_dict):
...     elements = inverted_dict.iteritems()
...     for flag_value, flag_names in elements:
...         for flag_name in flag_names:
...             yield flag_name, flag_value
... 
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Die Funktion invert_dict ist eine Generatorfunktion . Es erzeugt oder ergibt - was bedeutet, dass es gibt wiederholt Werte von - Schlüsselwertpaaren zurück. Diese Schlüssel-Wert-Paare sind die Umkehrung des Inhalts der beiden Elemente des anfänglichen Wörterbuchs flagsname__. Sie werden in den Konstruktor dicteingegeben. In diesem Fall funktioniert der Konstruktor dictanders als oben, da ihm ein Iterator und kein Wörterbuch als Argument übergeben wird.


Zeichnen auf @Chris Lutz Kommentar: Wenn Sie dies wirklich für Einzelzeichenwerte verwenden, können Sie dies tatsächlich tun

>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

Dies funktioniert, weil Python - Zeichenfolgen iterierbar sind, dh, sie können durch den Wert verschoben werden nach Wert. Im Fall einer Zeichenfolge sind die Werte die einzelnen Zeichen in der Zeichenfolge. Wenn sie also als iterable interpretiert werden, wie in diesem Fall, wenn sie in einer for-Schleife verwendet werden, sind ['a', 'b', 'c'] und 'abc' praktisch gleichwertig. Ein anderes Beispiel wäre, wenn sie an eine Funktion übergeben werden, die eine Iteration annimmt, wie TupleNAME _ .

Ich persönlich würde das nicht tun, weil es nicht intuitiv lesbar ist: Wenn ich eine Zeichenfolge sehe, erwarte ich, dass sie als einzelner Wert und nicht als Liste verwendet wird. Also schaue ich in die erste Zeile und denke: "Okay, es gibt also eine wahre Flagge und eine falsche Flagge." Also, obwohl es eine Möglichkeit ist, denke ich nicht, dass es der richtige Weg ist. Auf der anderen Seite kann es hilfreich sein, die Konzepte von Iterablen und Iteratoren klarer zu erklären.


Es ist auch keine schlechte Idee, die Funktion invert_dict so zu definieren, dass sie tatsächlich ein Wörterbuch zurückgibt. Ich habe das meistens einfach nicht gemacht, weil es nicht wirklich hilft zu erklären, wie die Routine funktioniert.


Anscheinend hat Python 2.7 Wörterbuchverständnisse, die eine äußerst übersichtliche Möglichkeit darstellen würden, diese Funktion zu implementieren. Dies ist eine Übung für den Leser, da ich Python 2.7 nicht installiert habe :)

Sie können auch einige Funktionen des vielseitigen Moduls itertools kombinieren. Wie sie sagen, Es gibt mehr als eine Möglichkeit, es zu tun . Warten Sie, die Python Leute sagen das nicht. Naja, in manchen Fällen ist es sowieso wahr. Ich würde vermuten, dass Guido uns Wörterbuchverständnisse gegeben hat, so dass es einen offensichtlichen Weg gibt, dies zu tun.

47
intuited
a, b, c, d, e, g, h, i, j = (True,)*9
f = False
192
Shariq

Verwenden Sie eine Liste/ein Wörterbuch oder definieren Sie Ihre eigene Klasse, um die Elemente, die Sie definieren, zu kapseln. Wenn Sie jedoch alle diese Variablen benötigen, können Sie Folgendes tun:

a = b = c = d = e = g = h = i = j = True
f = False
45
yan

Dies ist eine Ausarbeitung zu @ Jeff M s und meinen Kommentaren.

Wenn du das machst:

a, b = c, d

Es funktioniert mit Tupelpacken und Auspacken. Sie können die Schritte zum Einpacken und Auspacken trennen:

_ = c, d
a, b = _

In der ersten Zeile wird ein Tupel mit dem Namen _ erstellt, der zwei Elemente enthält, das erste mit dem Wert von c und das zweite mit dem Wert von d. Die zweite Zeile entpackt das _-Tuple in die Variablen a und b. Dies bricht Ihre eine große Linie zusammen:

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True

In zwei kleinere Zeilen:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _

Sie erhalten genau das gleiche Ergebnis wie die erste Zeile (einschließlich derselben Ausnahme, wenn Sie einem Teil Werte oder Variablen hinzufügen, aber vergessen, den anderen zu aktualisieren). In diesem speziellen Fall ist yans Antwort aber vielleicht die beste.

Wenn Sie eine Liste mit Werten haben, können Sie sie trotzdem auspacken. Sie müssen es nur in ein Tuple konvertieren. Im Folgenden wird beispielsweise jeder von a bis j ein Wert zwischen 0 und 9 zugewiesen:

a, b, c, d, e, f, g, h, i, j = Tuple(range(10))

EDIT: Ein ordentlicher Trick, um alle mit Ausnahme von Element 5 (Variable f) als wahr zuzuweisen:

a, b, c, d, e, f, g, h, i, j = Tuple(x != 5 for x in range(10))
9
Chris Lutz

Wenn Leute vorschlagen, "eine Liste oder ein Tuple oder eine andere Datenstruktur zu verwenden", sagen sie, dass, wenn Sie viele verschiedene Werte haben, die Sie interessieren, es nicht unbedingt der beste Weg ist, sie einzeln als lokale Variablen zu benennen Sachen machen.

Sie können sie stattdessen in einer größeren Datenstruktur zusammenfassen, die in einer einzelnen lokalen Variablen gespeichert werden kann.

intuited zeigte, wie Sie ein Wörterbuch dafür verwenden könnten, und Chris Lutz zeigte, wie ein Tuple zum temporären Speichern verwendet wird, bevor er in separate Variablen entpackt wird. Eine andere Option ist die Verwendung von collections.namedtuple, um die Werte dauerhaft zu bündeln.

Sie könnten also so etwas tun:

# Define the attributes of our named Tuple
from collections import namedtuple
DataHolder = namedtuple("DataHolder", "a b c d e f g")

# Store our data
data = DataHolder(True, True, True, True, True, False, True)

# Retrieve our data
print(data)
print(data.a, data.f)

Echter Code würde hoffentlich aussagekräftigere Namen als "DataHolder" und die Buchstaben des Alphabets verwenden.

5
ncoghlan

Was ist eigentlich das Problem? 

Wenn Sie wirklich brauchen oder wollen, 10 a, b, c, d, e, f, g, h, i, j, es gibt keine andere Möglichkeit, zu einer bestimmten Zeit, schreibe a und schreibe b und schreibe c.....

Wenn alle Werte unterschiedlich sind, müssen Sie beispielsweise schreiben

a = 12
b= 'Sun'
c = A() #(where A is a class)
d = range(1,102,5)
e = (line in filehandler if line.rstrip())
f = 0,12358
g = True
h = random.choice
i = re.compile('^(!=  ab).+?<span>')
j = [78,89,90,0]

das heißt, die "Variablen" werden einzeln definiert.

Oder, wenn Sie eine andere Schrift verwenden, müssen Sie _ nicht verwenden:

a,b,c,d,e,f,g,h,i,j =\
12,'Sun',A(),range(1,102,5),\
(line for line in filehandler if line.rstrip()),\
0.12358,True,random.choice,\
re.compile('^(!=  ab).+?<span>'),[78,89,90,0]

oder

a,b,c,d,e,f,g,h,i,j =\
(12,'Sun',A(),range(1,102,5),
 (line for line in filehandler if line.rstrip()),
 0.12358,True,random.choice,
 re.compile('^(!=  ab).+?<span>'),[78,89,90,0])

.

Wenn einige von ihnen denselben Wert haben müssen, besteht das Problem, dass es zu lang ist, um zu schreiben 

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True 

?

Dann kannst du schreiben:

a=b=c=d=e=g=h=i=k=j=True
f = False

.

Ich verstehe nicht, was genau dein Problem ist. Wenn Sie einen Code schreiben möchten, müssen Sie die für das Schreiben der Anweisungen und Definitionen erforderlichen Zeichen verwenden. Was sonst ? 

Ich frage mich, ob Ihre Frage nicht das Zeichen dafür ist, dass Sie etwas falsch verstehen.

Wenn man a = 10 schreibt, man erstellt keine Variable im Sinne von "Speicherplatz, dessen Wert sich ändern kann". Diese Anweisung:

  • entweder löst die Erstellung eines Objekts vom Typ integer und Wert 10 und die Bindung eines Namens 'a' mit diesem Objekt im aktuellen Namespace aus 

  • oder weisen Sie dem Objekt 10 den Namen 'a' im Namensraum zu (da 'a' zuvor an ein anderes Objekt gebunden war).

Ich sage das, weil ich das Dienstprogramm nicht sehe, um 10 Bezeichner a, b, c zu definieren, die auf False oder True zeigen. Wenn sich diese Werte während der Ausführung nicht ändern, warum 10 Bezeichner? Und wenn sie sich ändern, warum werden zuerst die Bezeichner definiert? Diese werden bei Bedarf erstellt, wenn sie nicht zuvor definiert wurden

Ihre Frage erscheint mir komisch

4
eyquem

Klingt so, als ob Sie Ihr Problem falsch angehen.

Schreiben Sie Ihren Code um, um ein Tuple zu verwenden, oder schreiben Sie eine Klasse zum Speichern aller Daten.

2
richo

Ich mag die am besten gewählte Antwort. Es hat jedoch Probleme mit der Liste wie gezeigt.

  >> a, b = ([0]*5,)*2
  >> print b
  [0, 0, 0, 0, 0]
  >> a[0] = 1
  >> print b
  [1, 0, 0, 0, 0]

Das wird ausführlich besprochen (hier) , aber der Kern ist, dass a und b dasselbe Objekt sind, wobei a is bTrue (das gleiche für id(a) == id(b)) zurückgibt. Wenn Sie also einen Index ändern, ändern Sie den Index von a und b, da sie miteinander verknüpft sind. Um dies zu lösen, können Sie (Quelle)

>> a, b = ([0]*5 for i in range(2))
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[0, 0, 0, 0, 0]

Dies kann dann als eine Variante der obersten Antwort verwendet werden, die die "gewünschten" intuitiven Ergebnisse hat

>> a, b, c, d, e, g, h, i = (True for i in range(9))
>> f = (False for i in range(1)) #to be pedantic
0
Novice C