1414 Stimmen

Versteckte Funktionen von Python

288voto

rlerallut Punkte 7067

Die for...else-Syntax (siehe http://docs.python.org/ref/for.html )

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

Der "else"-Block wird normalerweise am Ende der for-Schleife ausgeführt, es sei denn, die Pause wird aufgerufen.

Der obige Code könnte wie folgt emuliert werden:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")

219 Stimmen

Ich denke, die for/else-Syntax ist umständlich. Es "fühlt" sich so an, als sollte die else-Klausel ausgeführt werden, wenn der Schleifenkörper nie ausgeführt wird.

0 Stimmen

Es wird weniger unangenehm, wenn wir es als for/if/else betrachten, wobei das else zum if gehört. Und es ist eine so nützliche Redewendung, dass ich mich wundere, dass andere Sprachdesigner nicht darauf gekommen sind!

14 Stimmen

Ah. Das habe ich noch nie gesehen! Aber ich muss sagen, dass es ein wenig falsch bezeichnet ist. Wer würde erwarten, dass der else-Block nur ausgeführt wird, wenn break nie ausgeführt wird? Ich stimme mit codeape überein: Es sieht so aus, als ob else für leere Foos eingegeben wird.

258voto

Armin Ronacher Punkte 31082

Ab Version 2.5 haben Dicts eine spezielle Methode __missing__ die bei fehlenden Einträgen aufgerufen wird:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Es gibt auch eine Unterklasse dict in collections genannt. defaultdict die so ziemlich dasselbe tut, aber eine Funktion ohne Argumente für nicht vorhandene Elemente aufruft:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Ich empfehle, solche Dicts in reguläre Dicts zu konvertieren, bevor sie an Funktionen übergeben werden, die solche Unterklassen nicht erwarten. Eine Menge Code verwendet d[a_key] und fängt KeyErrors ab, um zu prüfen, ob ein Element existiert, das ein neues Element zum Diktat hinzufügen würde.

0 Stimmen

Hier lege ich Gabelbomben ab.

10 Stimmen

Ich verwende lieber setdefault. m={} ; m.setdefault('foo',1)

22 Stimmen

@grayger meinte dies m={}; m.setdefault('foo', []).append(1) .

247voto

Lucas S. Punkte 13041

Austausch von Werten an Ort und Stelle

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

Die rechte Seite der Zuweisung ist ein Ausdruck, der ein neues Tupel erzeugt. Die linke Seite der Zuweisung packt dieses (nicht referenzierte) Tupel sofort in die Namen a y b .

Nach der Zuweisung wird das neue Tupel nicht referenziert und für die Garbage Collection markiert, und die Werte, die an a y b ausgetauscht worden sind.

Wie in der Python-Tutorial Abschnitt über Datenstrukturen ,

Beachten Sie, dass die Mehrfachzuweisung eigentlich nur eine Kombination aus Tupel-Packing und Sequence-Unpacking ist.

1 Stimmen

Wird auf diese Weise mehr Arbeitsspeicher verbraucht als auf herkömmliche Weise? Ich würde vermuten, dass dies der Fall ist, da Sie ein Tupel erstellen, anstatt nur eine Swap-Variable

75 Stimmen

Es wird nicht mehr Speicherplatz benötigt. Es verbraucht weniger. Ich habe es einfach in beide Richtungen geschrieben und den Bytecode dekompiliert... der Compiler optimiert, wie man es sich erhofft. dis Ergebnisse zeigten, dass es die Variablen einrichtet und dann ROT_TWOing. ROT_TWO bedeutet 'Tausche die beiden obersten Stack-Vars'... Ziemlich schick, eigentlich.

5 Stimmen

Sie weisen auch versehentlich auf eine andere nette Eigenschaft von Python hin, nämlich dass Sie implizit ein Tupel von Elementen bilden können, indem Sie sie einfach durch Kommas trennen.

235voto

MvdD Punkte 19735

Lesbare reguläre Ausdrücke

In Python können Sie einen regulären Ausdruck über mehrere Zeilen aufteilen, Ihre Treffer benennen und Kommentare einfügen.

Beispiel für eine ausführliche Syntax (aus Eintauchen in Python ):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

Beispiel für Namensübereinstimmungen (von Reguläre Ausdrücke HOWTO )

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

Sie können eine Regex auch ausführlich schreiben, ohne re.VERBOSE dank der Verkettung von String-Literalen.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

7 Stimmen

Ich weiß nicht, ob ich das wirklich als ein Python-Feature betrachten würde, die meisten RE-Engines haben eine ausführliche Option.

18 Stimmen

Ja, aber weil man das nicht in grep oder in den meisten Editoren machen kann, wissen viele Leute nicht, dass es das gibt. Die Tatsache, dass andere Sprachen eine gleichwertige Funktion haben, bedeutet nicht, dass es nicht eine nützliche und wenig bekannte Funktion von Python ist

7 Stimmen

In einem großen Projekt mit vielen optimierten regulären Ausdrücken (sprich: optimiert für Maschinen, aber nicht für Menschen) habe ich in den sauren Apfel gebissen und sie alle in eine ausführliche Syntax umgewandelt. Jetzt ist es viel einfacher, neue Entwickler in die Projekte einzuführen. Von nun an schreiben wir für jedes Projekt ausführliche REs vor.

222voto

e-satis Punkte 547539

Entpacken von Funktionsargumenten

Sie können eine Liste oder ein Wörterbuch als Funktionsargumente auspacken, indem Sie * y ** .

Zum Beispiel:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Sehr nützliche Abkürzung, da Listen, Tupel und Dicts häufig als Container verwendet werden.

0 Stimmen

Ich benutze es ständig und liebe es.

27 Stimmen

* ist auch als Splat-Operator bekannt

3 Stimmen

Ich mag diese Funktion, aber pylint hat sie leider nicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X