Suche…


Einführung

Python ist eine Sprache, die klar und lesbar sein soll, ohne Unklarheiten und unerwartete Verhaltensweisen. Leider sind diese Ziele nicht in allen Fällen erreichbar. Aus diesem Grund gibt es in Python einige Eckpunkte, in denen es möglicherweise etwas anderes tut als erwartet.

In diesem Abschnitt werden einige Probleme beschrieben, die beim Schreiben von Python-Code auftreten können.

Ändern Sie die Reihenfolge, die Sie durchlaufen

Eine for Schleife durchläuft eine Sequenz, daher kann das Ändern dieser Sequenz innerhalb der Schleife zu unerwarteten Ergebnissen führen (insbesondere beim Hinzufügen oder Entfernen von Elementen):

alist = [0, 1, 2]
for index, value in enumerate(alist):
    alist.pop(index)
print(alist)
# Out: [1]

Hinweis: Mit list.pop() werden Elemente aus der Liste entfernt.

Das zweite Element wurde nicht gelöscht, da die Iteration der Reihe nach die Indizes durchläuft. Die obige Schleife wiederholt sich zweimal mit folgenden Ergebnissen:

# Iteration #1
index = 0
alist = [0, 1, 2]
alist.pop(0) # removes '0'

# Iteration #2
index = 1
alist = [1, 2]
alist.pop(1) # removes '2'

# loop terminates, but alist is not empty:
alist = [1]

Dieses Problem tritt auf, weil sich die Indizes ändern, während sie sich in Richtung des Indexanstiegs ändern. Um dieses Problem zu vermeiden, können Sie die Schleife rückwärts durchlaufen :

alist = [1,2,3,4,5,6,7]
for index, item in reversed(list(enumerate(alist))):
    # delete all even items
    if item % 2 == 0:
        alist.pop(index)
print(alist)
# Out: [1, 3, 5, 7]

Wenn Sie die Schleife am Ende durchlaufen und Elemente entfernen (oder hinzufügen), hat dies keinen Einfluss auf die Indexe der Elemente, die sich zuvor in der Liste befanden. In diesem Beispiel werden also alle Elemente, die auch von alist stammen, alist .


Ein ähnliches Problem entsteht beim Einfügen oder Anhängen von Elementen an eine Liste, die Sie durchlaufen , was zu einer Endlosschleife führen kann:

alist = [0, 1, 2]
for index, value in enumerate(alist):
    # break to avoid infinite loop:
    if index == 20:     
        break           
    alist.insert(index, 'a')
print(alist)
# Out (abbreviated): ['a', 'a', ..., 'a', 'a',  0,   1,   2]

Ohne die break fügt die Schleife 'a' solange dem Computer nicht genügend Speicher zur Verfügung steht und das Programm weiterlaufen darf. In einer Situation wie dieser wird normalerweise bevorzugt, eine neue Liste zu erstellen und der neuen Liste Elemente hinzuzufügen, während Sie die ursprüngliche Liste durchlaufen.


Bei Verwendung einer for Schleife können Sie die Listenelemente nicht mit der Platzhaltervariablen ändern :

alist = [1,2,3,4]
for item in alist:
    if item % 2 == 0:
        item = 'even'
print(alist)
# Out: [1,2,3,4]

Im obigen Beispiel ändert das Ändern eines item nichts an der ursprünglichen Liste . Sie müssen den alist[2] ( alist[2] ) verwenden, und enumerate() funktioniert dafür gut:

alist = [1,2,3,4]
for index, item in enumerate(alist):
    if item % 2 == 0:
        alist[index] = 'even'
print(alist)
# Out: [1, 'even', 3, 'even']

Eine while Schleife ist in manchen Fällen die bessere Wahl:

Wenn Sie alle Elemente in der Liste löschen möchten :

zlist = [0, 1, 2]
while zlist:
    print(zlist[0])
    zlist.pop(0)
print('After: zlist =', zlist)

# Out: 0
#      1
#      2
# After: zlist = []

Wenn Sie zlist einfach zurücksetzen, zlist dasselbe Ergebnis.

zlist = []

Das obige Beispiel kann auch mit len() kombiniert werden, um nach einem bestimmten Punkt zu stoppen oder um alle Elemente außer x zu löschen:

zlist = [0, 1, 2]
x = 1
while len(zlist) > x:
    print(zlist[0])
    zlist.pop(0)
print('After: zlist =', zlist)

# Out: 0
#      1
# After: zlist = [2]

Oder zum Durchlaufen einer Liste, während Elemente gelöscht werden, die eine bestimmte Bedingung erfüllen (in diesem Fall werden alle geraden Elemente gelöscht):

zlist = [1,2,3,4,5]
i = 0
while i < len(zlist):
    if zlist[i] % 2 == 0:
        zlist.pop(i)
    else:
        i += 1
print(zlist)
# Out: [1, 3, 5]

Beachten Sie, dass Sie i nicht erhöhen, nachdem Sie ein Element gelöscht haben. Durch das Löschen des Elements in zlist[i] hat sich der Index des nächsten Elements um eins verringert. zlist[i] mit demselben Wert für i bei der nächsten Iteration überprüfen, werden Sie das nächste Element in der Liste korrekt überprüfen .


Ein anderer Weg, über das Entfernen unerwünschter Elemente aus einer Liste nachzudenken, besteht darin , gewünschte Elemente zu einer neuen Liste hinzuzufügen . Das folgende Beispiel ist eine Alternative zu diesem Beispiel while Schleife:

zlist = [1,2,3,4,5]

z_temp = []
for item in zlist:
    if item % 2 != 0:
        z_temp.append(item)
zlist = z_temp
print(zlist)
# Out: [1, 3, 5]

Hier führen wir die gewünschten Ergebnisse in eine neue Liste ein. Die temporäre Liste kann dann optional der ursprünglichen Variablen zugewiesen werden.

Mit diesem Gedankengang können Sie eine der elegantesten und leistungsstärksten Funktionen von Python aufrufen, Listenverständnisse , die temporäre Listen eliminieren und von der zuvor diskutierten In-Place-Liste / Index-Mutationsideologie abweichen.

zlist = [1,2,3,4,5]
[item for item in zlist if item % 2 != 0]
# Out: [1, 3, 5]

Veränderliches Standardargument

def foo(li=[]):
    li.append(1)
    print(li)

foo([2])
# Out: [2, 1]
foo([3])
# Out: [3, 1]

Dieser Code verhält sich wie erwartet, aber was ist, wenn wir kein Argument übergeben?

foo()
# Out: [1] As expected...

foo()
# Out: [1, 1]  Not as expected...

Dies liegt daran, dass Standardargumente von Funktionen und Methoden nicht zur Laufzeit, sondern zur Definitionszeit ausgewertet werden. Also nur wir jemals eine einzige Instanz der haben li Liste.

Um dies zu umgehen, verwenden Sie nur unveränderliche Typen für Standardargumente:

def foo(li=None):
    if not li:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]

foo()
# Out: [1]

Eine Verbesserung und if not li korrekt als False ausgewertet, gilt dies für viele andere Objekte, z. Die folgenden Beispielargumente können zu unbeabsichtigten Ergebnissen führen:

x = []
foo(li=x)
# Out: [1]

foo(li="")
# Out: [1]

foo(li=0) 
# Out: [1]

Der idiomatische Ansatz besteht darin, das Argument direkt gegen das None Objekt zu prüfen:

def foo(li=None):
    if li is None:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]

Listenmultiplikation und gemeinsame Referenzen

Betrachten Sie den Fall der Erstellung einer verschachtelten Listenstruktur durch Multiplikation:

li = [[]] * 3
print(li)
# Out: [[], [], []]

Auf den ersten Blick denken wir, wir hätten eine Liste mit 3 verschachtelten Listen. Versuchen wir, 1 an die erste anzuhängen:

li[0].append(1)
print(li)
# Out: [[1], [1], [1]]

1 wurde auf alle Listen in den beigefügten li .

Der Grund ist, dass [[]] * 3 keine list mit 3 verschiedenen list . Vielmehr erstellt er eine list mit mindestens 3 Verweise auf die gleiche list Objekt. Wenn wir also an li[0] anhängen, ist die Änderung in allen Unterelementen von li sichtbar. Dies ist gleichbedeutend mit:

li = []
element = [[]]
li = element + element + element
print(li)
# Out: [[], [], []]
element.append(1)
print(li)
# Out: [[1], [1], [1]]

Dies kann weiter bestätigt werden, wenn wir die Speicheradressen der enthaltenen list mit id ausdrucken:

li = [[]] * 3
print([id(inner_list) for inner_list in li])
# Out: [6830760, 6830760, 6830760]

Die Lösung besteht darin, die inneren Listen mit einer Schleife zu erstellen:

li = [[] for _ in range(3)]

Anstatt eine einzige list erstellen und anschließend drei Verweise darauf zu erstellen, erstellen wir nun drei unterschiedliche Listen. Dies kann wiederum mit der id Funktion überprüft werden:

print([id(inner_list) for inner_list in li])
# Out: [6331048, 6331528, 6331488]

Sie können das auch tun. Es bewirkt, dass bei jedem append Aufruf eine neue leere Liste erstellt wird.

>>> li = []
>>> li.append([])
>>> li.append([])
>>> li.append([])
>>> for k in li: print(id(k))
... 
4315469256
4315564552
4315564808

Verwenden Sie den Index nicht, um eine Sequenz zu durchlaufen.

Nicht:

for i in range(len(tab)):
    print(tab[i])

Tun :

for elem in tab:
    print(elem)

for wird die meisten Iterationsvorgänge für Sie automatisieren.

Verwenden Sie Aufzählung, wenn Sie wirklich sowohl den Index als auch das Element benötigen .

for i, elem in enumerate(tab):
     print((i, elem))

Seien Sie vorsichtig, wenn Sie "==" verwenden, um nach "Wahr" oder "Falsch" zu suchen

if (var == True):
    # this will execute if var is True or 1, 1.0, 1L

if (var != True):
    # this will execute if var is neither True nor 1

if (var == False):
    # this will execute if var is False or 0 (or 0.0, 0L, 0j)

if (var == None):
    # only execute if var is None

if var:
    # execute if var is a non-empty string/list/dictionary/tuple, non-0, etc

if not var:
    # execute if var is "", {}, [], (), 0, None, etc.

if var is True:
    # only execute if var is boolean True, not 1

if var is False:
    # only execute if var is boolean False, not 0

if var is None:
    # same as var == None

Überprüfen Sie nicht, ob Sie dies tun können, und führen Sie den Fehler aus

Pythonistas sagen normalerweise "Es ist einfacher, um Vergebung zu bitten als um Erlaubnis".

Nicht:

if os.path.isfile(file_path):
    file = open(file_path)
else:
    # do something

Tun:

try:
    file = open(file_path)
except OSError as e:
    # do something

Oder noch besser mit Python 2.6+ :

with open(file_path) as file:

Es ist viel besser, weil es viel generischer ist. Sie können try/except auf fast alles anwenden. Sie müssen sich nicht darum kümmern, was zu tun ist, um dies zu verhindern, sondern nur den Fehler, den Sie riskieren.

Nicht gegen Typ prüfen

Python ist dynamisch typisiert. Wenn Sie also nach Typ suchen, verlieren Sie die Flexibilität. Verwenden Sie stattdessen das Eingeben von Enten, indem Sie das Verhalten überprüfen. Wenn Sie eine Zeichenfolge in einer Funktion erwarten, konvertieren Sie ein Objekt mit str() in eine Zeichenfolge. Wenn Sie mit einer Liste rechnen, verwenden Sie list() , um alle Iterierbaren in eine Liste zu konvertieren.

Nicht:

def foo(name):
    if isinstance(name, str):
        print(name.lower())

def bar(listing):
    if isinstance(listing, list):
        listing.extend((1, 2, 3))
        return ", ".join(listing)

Tun:

def foo(name) :
    print(str(name).lower())

def bar(listing) :
    l = list(listing)
    l.extend((1, 2, 3))
    return ", ".join(l)

Auf die letzte Weise akzeptiert foo jedes Objekt. bar akzeptiert Strings, Tupel, Sets, Listen und vieles mehr. Billig TROCKEN.

Mischen Sie keine Leerzeichen und Tabulatoren

Objekt als erstes übergeordnetes Objekt verwenden

Das ist knifflig, aber es wird Sie beißen, wenn Ihr Programm wächst. In Python 2.x gibt es alte und neue Klassen. Die Alten sind gut, alt. Sie verfügen nicht über einige Funktionen und können bei der Vererbung unangenehm sein. Um nutzbar zu sein, muss jede Ihrer Klassen den "neuen Stil" haben. Dazu machen Sie es vom object erben.

Nicht:

class Father:
    pass

class Child(Father):
    pass

Tun:

class Father(object):
    pass


class Child(Father):
    pass

In Python 3.x alle Klassen einen neuen Stil, so dass Sie dies nicht tun müssen.

Initialisieren Sie Klassenattribute nicht außerhalb der init- Methode

Menschen, die aus anderen Sprachen kommen, finden es verlockend, weil Sie dies in Java oder PHP tun. Sie schreiben den Klassennamen, listen Ihre Attribute auf und geben ihnen einen Standardwert. Es scheint in Python zu funktionieren, aber das funktioniert nicht so, wie Sie denken. Dadurch werden Klassenattribute (statische Attribute) eingerichtet. Wenn Sie versuchen, das Objektattribut abzurufen, erhalten Sie dessen Wert, wenn es nicht leer ist. In diesem Fall werden die Klassenattribute zurückgegeben. Daraus ergeben sich zwei große Gefahren:

  • Wenn das Klassenattribut geändert wird, wird der Anfangswert geändert.

  • Wenn Sie ein veränderbares Objekt als Standardwert festlegen, wird dasselbe Objekt für alle Instanzen gemeinsam verwendet.

Nicht (es sei denn, Sie möchten statisch):

class Car(object):
    color = "red"
    wheels = [Wheel(), Wheel(), Wheel(), Wheel()]

Tun :

class Car(object):
    def __init__(self):
        self.color = "red"
        self.wheels = [Wheel(), Wheel(), Wheel(), Wheel()]

Integer- und String-Identität

Python verwendet internes Caching für eine Reihe von ganzen Zahlen, um den unnötigen Aufwand durch wiederholtes Erstellen zu reduzieren.

Dies kann zu einem verwirrenden Verhalten beim Vergleich von Integer-Identitäten führen:

>>> -8 is (-7 - 1)
False
>>> -3 is (-2 - 1)
True

und mit einem anderen Beispiel:

>>> (255 + 1) is (255 + 1)
True
>>> (256 + 1) is (256 + 1)
False

Warte was?

Wir können sehen , dass die Identität Betrieb is Ausbeuten True für einige ganze Zahlen ( -3 , 256 ) , aber nicht für andere ( -8 , 257 ).

Genauer gesagt, Ganzzahlen im Bereich [-5, 256] werden beim Start des Interpreters intern zwischengespeichert und nur einmal erstellt. Als solche sind sie identisch und mit ihrer Identität zu vergleichen is ergibt True ; Ganzzahlen außerhalb dieses Bereichs werden (normalerweise) on-the-fly erstellt und ihre Identitäten werden mit False verglichen.

Dies ist eine häufige Fallstricke, da dies ein üblicher Bereich für Tests ist, aber oft genug versagt der Code beim späteren Bereitstellungsprozess (oder schlechterer Produktion), ohne dass ein offensichtlicher Grund vorliegt, nachdem er in der Entwicklung perfekt gearbeitet hat.

Die Lösung besteht darin , Werte immer mit dem Gleichheitsoperator ( == ) und nicht mit dem Identitätsoperator ( is ) zu vergleichen.


Python hält auch Strings häufig verwendete Verweise auf und in ähnlicher Weise verwirrende Verhalten führen können , wenn Identitäten zu vergleichen (dh unter Verwendung is ) von Strings.

>>> 'python' is 'py' + 'thon'
True

Die Zeichenfolge 'python' wird häufig verwendet, daher hat Python ein Objekt, das alle Verweise auf die Zeichenfolge 'python' verwenden.

Bei ungewöhnlichen Zeichenfolgen schlägt der Vergleich der Identität fehl, selbst wenn die Zeichenfolgen gleich sind.

>>> 'this is not a common string' is 'this is not' + ' a common string'
False
>>> 'this is not a common string' == 'this is not' + ' a common string'
True

Vergleichen Sie die Zeichenfolgenwerte wie bei der Ganzzahl immer mit dem Gleichheitsoperator ( == ) und nicht mit dem Identitätsoperator ( is ).

Zugriff auf Attribute von Int-Literalen

Sie haben vielleicht gehört, dass alles in Python ein Objekt ist, sogar Literale. Dies bedeutet beispielsweise, dass 7 ein Objekt ist, das heißt, es hat Attribute. Eines dieser Attribute ist beispielsweise die bit_length . Es gibt die Menge an Bits zurück, die zur Darstellung des Werts benötigt wird, für den er aufgerufen wird.

x = 7
x.bit_length()
# Out: 3

Wenn Sie sehen, dass der obige Code funktioniert, könnten Sie intuitiv denken, dass 7.bit_length() funktionieren würde, nur um herauszufinden, dass dies einen SyntaxError . Warum? weil der Interpreter zwischen einem Attributzugriff und einer Floating-Nummer unterscheiden muss (z. B. 7.2 oder 7.bit_length() ). Das kann nicht, und deshalb wird eine Ausnahme ausgelöst.

Es gibt verschiedene Möglichkeiten, auf die Attribute eines int Literalen zuzugreifen:

# parenthesis
(7).bit_length()
# a space
7 .bit_length()

Die Verwendung von zwei Punkten (wie 7..bit_length() ) funktioniert in diesem Fall nicht, da dadurch ein float Literal erstellt wird und Floats nicht über die bit_length() -Methode verfügen.

Dieses Problem besteht nicht beim Zugriff auf float Attribute der float Literale, da der Interperter "intelligent" genug ist, um zu wissen, dass ein float Literal nicht zwei enthalten kann . , zum Beispiel:

7.2.as_integer_ratio()
# Out: (8106479329266893, 1125899906842624)

Verkettung oder Operator

Beim Testen auf einen von mehreren Gleichheitsvergleichen:

if a == 3 or b == 3 or c == 3:

es ist verlockend, dies zu verkürzen

if a or b or c == 3: # Wrong

Das ist falsch; Der Operator or hat eine niedrigere Priorität als == . Der Ausdruck wird also wie if (a) or (b) or (c == 3): Der richtige Weg ist die explizite Überprüfung aller Bedingungen:

if a == 3 or b == 3 or c == 3:  # Right Way

Alternativ kann die eingebaute any() Funktion anstelle von verketteten or Operatoren verwendet werden:

if any([a == 3, b == 3, c == 3]): # Right

Oder, um es effizienter zu machen:

if any(x == 3 for x in (a, b, c)): # Right

Oder um es kürzer zu machen:

if 3 in (a, b, c): # Right

Hier verwenden wir die in Operator zu testen , ob der Wert in einem Tupel vorhanden ist , die Werte enthalten , die wir gegen vergleichen wollen.

Ebenso ist es falsch zu schreiben

if a == 1 or 2 or 3:

was sollte als geschrieben werden

if a in (1, 2, 3):

sys.argv [0] ist der Name der ausgeführten Datei

Das erste Element von sys.argv[0] ist der Name der gerade ausgeführten Python-Datei. Die restlichen Elemente sind die Skriptargumente.

# script.py
import sys

print(sys.argv[0])
print(sys.argv)

$ python script.py
=> script.py
=> ['script.py']

$ python script.py fizz
=> script.py
=> ['script.py', 'fizz']

$ python script.py fizz buzz
=> script.py
=> ['script.py', 'fizz', 'buzz']

Wörterbücher sind nicht geordnet

Sie können erwarten, dass ein Python-Wörterbuch nach Schlüsseln sortiert wird, z. B. einer C ++ std::map . Dies ist jedoch nicht der Fall:

myDict = {'first': 1, 'second': 2, 'third': 3}
print(myDict)
# Out: {'first': 1, 'second': 2, 'third': 3}

print([k for k in myDict])
# Out: ['second', 'third', 'first']

Python hat keine eingebaute Klasse, die ihre Elemente automatisch nach Schlüssel sortiert.

Wenn das Sortieren jedoch kein Muss ist und Sie möchten, dass sich das Wörterbuch nur an die Reihenfolge der Einfügung der Schlüssel / Wert-Paare erinnert, können Sie collections.OrderedDict verwenden. collections.OrderedDict :

from collections import OrderedDict

oDict = OrderedDict([('first', 1), ('second', 2), ('third', 3)])

print([k for k in oDict])
# Out: ['first', 'second', 'third']

OrderedDict Sie, dass das Initialisieren eines OrderedDict mit einem Standardwörterbuch das Wörterbuch in keiner Weise für Sie sortiert. Alles , was diese Struktur macht , ist die Reihenfolge der Schlüsseleinführungs zu bewahren.

Die Implementierung von Wörterbüchern wurde in Python 3.6 geändert , um den Speicherverbrauch zu verbessern. Ein Nebeneffekt dieser neuen Implementierung ist, dass auch die Reihenfolge der an eine Funktion übergebenen Schlüsselwortargumente beibehalten wird:

Python 3.x 3.6
def func(**kw): print(kw.keys())

func(a=1, b=2, c=3, d=4, e=5) 
dict_keys(['a', 'b', 'c', 'd', 'e']) # expected order 

Caveat: Vorsicht , dass „die Reihenfolge erhaltender Aspekt dieser neuen Implementierung wird eine Implementierung Detail betrachtet und soll nicht als verlässlich angesehen werden“ , wie es in der Zukunft ändern kann.

Globale Interpreter-Sperre (GIL) und blockierende Threads

Über Pythons GIL wurde viel geschrieben . Dies kann manchmal zu Verwirrung führen, wenn Sie mit Multi-Threaded-Anwendungen (nicht zu verwechseln mit Multiprozess-Anwendungen) umgehen.

Hier ist ein Beispiel:

import math
from threading import Thread

def calc_fact(num):
    math.factorial(num)

num = 600000
t = Thread(target=calc_fact, daemon=True, args=[num])
print("About to calculate: {}!".format(num))
t.start()
print("Calculating...")
t.join()
print("Calculated")

Sie würden erwarten, dass Calculating... direkt nach dem Start des Threads ausgedruckt wird. Wir wollten, dass die Berechnung in einem neuen Thread durchgeführt wird! Tatsächlich sehen Sie, dass es gedruckt wird, nachdem die Berechnung abgeschlossen ist. math.factorial liegt daran, dass der neue Thread auf einer C-Funktion ( math.factorial ) math.factorial die die GIL während der math.factorial sperrt.

Es gibt ein paar Möglichkeiten, dies zu umgehen. Die erste besteht darin, Ihre faktorielle Funktion in nativem Python zu implementieren. Dadurch kann der Haupt-Thread die Kontrolle übernehmen, während Sie sich in Ihrer Schleife befinden. Der Nachteil ist, dass diese Lösung viel langsamer ist, da wir die C-Funktion nicht mehr verwenden.

def calc_fact(num):
    """ A slow version of factorial in native Python """
    res = 1
    while num >= 1:
        res = res * num
        num -= 1
    return res

Sie können auch eine gewisse Zeit lang sleep bevor Sie mit der Ausführung beginnen. Hinweis: Dies erlaubt Ihrem Programm nicht, die Berechnung innerhalb der C-Funktion zu unterbrechen, aber Ihr Hauptthread kann nach dem Spawn fortfahren, was Sie vielleicht erwarten.

def calc_fact(num):
    sleep(0.001)
    math.factorial(num)

Variables Durchsickern in Listenverständnissen und für Schleifen

Betrachten Sie das folgende Listenverständnis

Python 2.x 2.7
i = 0
a = [i for i in range(3)]
print(i) # Outputs 2

Dies tritt nur in Python 2 auf, da das Listenverständnis die Schleifensteuerungsvariable in den umgebenden Geltungsbereich ( Quelle ) "leckt". Dieses Verhalten kann zu schwer zu findenden Fehlern führen und wurde in Python 3 behoben .

Python 3.x 3.0
i = 0
a = [i for i in range(3)]
print(i) # Outputs 0

Ebenso haben for-Schleifen keinen privaten Gültigkeitsbereich für ihre Iterationsvariable

i = 0
for i in range(3):
    pass
print(i) # Outputs 2

Diese Art von Verhalten tritt sowohl in Python 2 als auch in Python 3 auf.

Um Probleme mit undichten Variablen zu vermeiden, verwenden Sie neue Variablen in Listenverständnissen und für Schleifen.

Mehrfachrückgabe

Die Funktion xyz liefert zwei Werte a und b:

def xyz():
  return a, b

Code, der xyz aufruft, speichert das Ergebnis in einer Variablen, vorausgesetzt, xyz gibt nur einen Wert zurück:

t = xyz()

Der Wert von t ist eigentlich ein Tupel (a, b), sodass jede Aktion, die sich auf t bezieht, vorausgesetzt, dass es sich nicht um ein Tupel handelt, tief im Code mit einem unerwarteten Fehler in Bezug auf Tupel fehlschlagen kann.

TypeError: Typ Tupel definiert keine ... Methode

Die Lösung wäre zu tun:

a, b = xyz()

Anfänger werden Schwierigkeiten haben, den Grund für diese Nachricht zu finden, indem sie nur die Tupel-Fehlermeldung lesen!

Pythonic JSON-Schlüssel

my_var = 'bla';
api_key = 'key';
...lots of code here...
params = {"language": "en", my_var: api_key}

Wenn Sie mit JavaScript vertraut sind, ist die Variablenbewertung in Python-Wörterbüchern nicht das, was Sie erwarten. Diese Anweisung in JavaScript würde das params Objekt wie folgt ergeben:

{
    "language": "en",
    "my_var": "key"
}

In Python würde sich jedoch folgendes Wörterbuch ergeben:

{
    "language": "en",
    "bla": "key"
}

my_var wird ausgewertet und sein Wert wird als Schlüssel verwendet.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow