Versteckte Funktionen von Python [geschlossen]

1419

Was sind die weniger bekannten, aber nützlichen Funktionen der Programmiersprache Python?

  • Versuchen Sie, die Antworten auf den Python-Kern zu beschränken.
  • Eine Funktion pro Antwort.
  • Geben Sie ein Beispiel und eine kurze Beschreibung der Funktion, nicht nur einen Link zur Dokumentation.
  • Beschriften Sie das Feature mit einem Titel als erste Zeile.

Schnelle Links zu Antworten:

compie
quelle

Antworten:

740

Verketten von Vergleichsoperatoren:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

Wenn Sie denken, dass es funktioniert 1 < x, was herauskommt True, und dann vergleichen True < 10, was auch ist True, dann nein, das ist wirklich nicht das, was passiert (siehe das letzte Beispiel). Es übersetzt wirklich in 1 < x and x < 10und x < 10 and 10 < x * 10 and x*10 < 100, aber mit weniger Tippen und jedem Begriff wird nur einmal ausgewertet.

Thomas Wouters
quelle
121
Das ist sehr hilfreich. Es sollte für alle Sprachen Standard sein. Leider ist es nicht.
Stalepretzel
8
Sie sollten einige Beispiele hinzufügen, die ebenfalls false zurückgeben. wie >>> 10 <x <20 False
ShoeLace
19
Dies gilt auch für andere Vergleichsoperatoren, weshalb die Leute manchmal überrascht sind, warum Code wie (5 in [5] ist wahr) falsch ist (aber es ist unpythonisch, zunächst explizit gegen solche Booleschen Werte zu testen).
Meilen
19
Gut, aber achten Sie auf die gleiche Priorität wie 'in' und '='. 'A in B == C in D' bedeutet '(A in B) und (B == C) und (C in D)', was unerwartet sein kann.
Charles Merriam
15
Azafe: Lisps Vergleiche funktionieren natürlich so. Es ist kein Sonderfall, weil es keine andere (vernünftige) Art der Interpretation gibt (< 1 x 10). Sie können sie sogar auf einzelne Argumente anwenden, z. B (= 10).: Cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/…
Ken
512

Holen Sie sich den Python-Regex-Analysebaum, um Ihren Regex zu debuggen.

Reguläre Ausdrücke sind eine großartige Funktion von Python, aber das Debuggen kann schmerzhaft sein, und es ist allzu leicht, einen regulären Ausdruck falsch zu verstehen.

Glücklicherweise kann Python den Regex-Analysebaum drucken, indem das undokumentierte, experimentelle, versteckte Flag re.DEBUG(tatsächlich 128) an übergeben wird re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Sobald Sie die Syntax verstanden haben, können Sie Ihre Fehler erkennen. Dort können wir sehen, dass ich vergessen habe, dem []In zu entkommen [/font].

Natürlich können Sie es mit beliebigen Flags kombinieren, z. B. mit kommentierten regulären Ausdrücken:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)
BatchyX
quelle
3
Außer das Parsen von HTML mit regulären Ausdrücken ist langsam und schmerzhaft. Selbst das integrierte HTML-Parser-Modul verwendet keine regulären Ausdrücke, um die Arbeit zu erledigen. Und wenn Ihnen das HTML-Modul nicht gefällt, gibt es viele XML / HTML-Parser-Module, die den Job erledigen, ohne das Rad neu erfinden zu müssen.
BatchyX
Ein Link zur Dokumentation zur Ausgabesyntax wäre großartig.
Personman
1
Dies sollte ein offizieller Teil von Python sein, nicht experimentell ... RegEx ist immer schwierig und es ist wirklich hilfreich zu verfolgen, was passiert.
Cahit
460

aufzählen

Wenn Sie eine iterable Datei mit enumerate umschließen, wird das Element zusammen mit seinem Index angezeigt.

Zum Beispiel:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Verweise:

Dave
quelle
56
Ich bin überrascht, dass dies in Tutorials über Python-Listen nicht routinemäßig behandelt wird.
Draemon
45
Und die ganze Zeit habe ich so codiert: für i in range (len (a)): ... und dann ein [i] verwendet, um das aktuelle Element zu erhalten.
Fernando Martin
4
@ Berry Tsakala: Meines Wissens wurde es nicht veraltet.
JAB
23
Heiliger Mist, das ist großartig. für i in xrange (len (a)): war schon immer meine am wenigsten bevorzugte Python-Sprache.
Personman
15
Aufzählung kann von einem beliebigen Index ausgehen, nicht erforderlich 0. Beispiel: 'für i, Element in Aufzählung ( Liste , Start = 1): print i, Element' startet die Aufzählung von 1, nicht von 0.
dmitry_romanov
419

Generatorobjekte erstellen

Wenn du schreibst

x=(n for n in foo if bar(n))

Sie können den Generator herausholen und x zuweisen. Jetzt können Sie es tun

for n in x:

Dies hat den Vorteil, dass Sie keinen Zwischenspeicher benötigen, den Sie sonst benötigen würden

x = [n for n in foo if bar(n)]

In einigen Fällen kann dies zu einer erheblichen Beschleunigung führen.

Sie können viele if-Anweisungen an das Ende des Generators anhängen und im Grunde verschachtelte for-Schleifen replizieren:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)
Freiraum
quelle
Sie könnten dafür auch ein verschachteltes Listenverständnis verwenden, ja?
Shapr
54
Besonders hervorzuheben ist die Speicherkostenersparnis. Die Werte werden bei Bedarf berechnet, sodass Sie nie das gesamte Ergebnis des Listenverständnisses im Speicher haben. Dies ist besonders wünschenswert, wenn Sie später nur einen Teil des Listenverständnisses durchlaufen.
Saffsd
19
Dies ist imo nicht besonders "versteckt", aber es ist auch erwähnenswert, dass Sie ein Generatorobjekt nicht zurückspulen konnten, während Sie eine Liste beliebig oft wiederholen können.
Susmits
13
Die Funktion "Kein Zurückspulen" von Generatoren kann zu Verwirrung führen. Insbesondere wenn Sie den Inhalt eines Generators zum Debuggen drucken und ihn später zum Verarbeiten der Daten verwenden, funktioniert dies nicht. Die Daten werden erzeugt, von print () verbraucht und stehen dann für die normale Verarbeitung nicht zur Verfügung. Dies gilt nicht für Listenverständnisse, da diese vollständig im Speicher gespeichert sind.
Johntellsall
4
Ähnliche (dup?) Antwort: stackoverflow.com/questions/101268/hidden-features-of-python/… Beachten Sie jedoch, dass die Antwort, die ich hier verlinkt habe, eine WIRKLICH GUTE Präsentation über die Leistung von Generatoren erwähnt. Sie sollten es wirklich überprüfen.
Denilson Sá Maia
353

iter () kann ein aufrufbares Argument annehmen

Zum Beispiel:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

Die iter(callable, until_value)Funktion ruft wiederholt auf callableund gibt das Ergebnis aus, bis until_valuees zurückgegeben wird.

mbac32768
quelle
Können Sie als Python-Neuling erklären, warum das lambdaSchlüsselwort hier erforderlich ist?
SiegeX
@SiegeX ohne Lambda würde f.read (1) ausgewertet (Rückgabe eines Strings), bevor es an die Iter-Funktion übergeben wird. Stattdessen erstellt das Lambda eine anonyme Funktion und übergibt diese an iter.
Jmilloy
339

Seien Sie vorsichtig mit veränderlichen Standardargumenten

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Verwenden Sie stattdessen einen Sentinel-Wert, der "nicht angegeben" bedeutet, und ersetzen Sie ihn durch die veränderbare Variable, die Sie standardmäßig verwenden möchten:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]
Jason Baker
quelle
39
Das ist definitiv eine der bösartigsten versteckten Funktionen. Ich bin von Zeit zu Zeit darauf gestoßen.
Torsten Marek
77
Ich fand das viel einfacher zu verstehen, als ich erfuhr, dass die Standardargumente in einem Tupel leben, das ein Attribut der Funktion ist, z foo.func_defaults. Was als Tupel unveränderlich ist.
Robert Rossney
2
@grayger: Während die def-Anweisung ausgeführt wird, werden ihre Argumente vom Interpreter ausgewertet. Dadurch wird ein Name für ein Codeobjekt (die Suite der Funktion) erstellt (oder erneut gebunden). Die Standardargumente werden jedoch zum Zeitpunkt der Definition als Objekte instanziiert. Dies gilt für jede Zeit eines Standardobjekts, ist jedoch nur dann von Bedeutung (Offenlegung der sichtbaren Semantik), wenn das Objekt veränderbar ist. Es gibt keine Möglichkeit, diesen Standardargumentnamen beim Schließen der Funktion neu zu binden, obwohl er offensichtlich für jeden Aufruf überschrieben werden kann oder die gesamte Funktion neu definiert werden kann.
Jim Dennis
3
@ Robert Natürlich können die Argumente Tupel unveränderlich sein, aber die Objekte, auf die es zeigt, sind nicht unbedingt unveränderlich.
Poolie
16
Ein kurzer Hack, um Ihre Initialisierung etwas kürzer zu machen: x = x oder []. Sie können dies anstelle der 2-zeiligen if-Anweisung verwenden.
Dave Mankoff
317

Senden von Werten in Generatorfunktionen . Zum Beispiel mit dieser Funktion:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

Du kannst:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7
Rafał Dowgird
quelle
Einverstanden. Betrachten wir dies als ein böses Beispiel für eine versteckte Funktion von Python :)
Rafał Dowgird
89
In anderen Sprachen glaube ich, dass dieses magische Gerät als "Variable" bezeichnet wird.
Finnw
5
Coroutinen sollten Coroutinen sein und Genenerator sollte auch sie selbst sein, ohne sich zu vermischen. Mega-toller Link und Talk und Beispiele dazu hier: dabeaz.com/coroutines
u0b34a0f6ae
31
@finnw: Das Beispiel implementiert etwas, das einer Variablen ähnlich ist. Die Funktion kann jedoch auf viele andere Arten verwendet werden ... im Gegensatz zu einer Variablen. Es sollte auch klar sein , dass ähnliche Semantik Objekte implementiert werden kann unter Verwendung (eine Klasse implemting Pythons Anrufverfahren, insbesondere).
Jim Dennis
4
Dies ist ein zu triviales Beispiel für Menschen, die Co-Routinen noch nie gesehen haben (und wahrscheinlich auch nicht verstehen werden). Das Beispiel, das den laufenden Durchschnitt ohne das Risiko eines Überlaufs der Summenvariablen implementiert, ist gut.
Prashant Kumar
313

Wenn Sie keine Leerzeichen verwenden möchten, um Bereiche zu kennzeichnen, können Sie den C-Stil {} verwenden, indem Sie Folgendes ausgeben:

from __future__ import braces
nervös
quelle
122
Das ist böse. :)
Jason Baker
37
>>> aus __future__ Klammern importieren Datei "<stdin>", Zeile 1 SyntaxError: keine Chance: P
Benjamin W. Smith
40
das ist Gotteslästerung!
Berk D. Demir
335
Ich denke, dass wir hier einen syntaktischen Fehler haben könnten, sollte das nicht "aus __past__ Importklammern " sein?
Bill K
47
von __cruft__ importieren Zahnspangen
Phillip B Oldham
305

Das Schrittargument in Slice-Operatoren. Zum Beispiel:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

Der Sonderfall x[::-1]ist eine nützliche Redewendung für 'x umgekehrt'.

>>> a[::-1]
[5,4,3,2,1]
Rafał Dowgird
quelle
31
Viel klarer ist meiner Meinung nach die Funktion reverse (). >>> Liste (umgekehrt (Bereich (4))) [3, 2, 1, 0]
Christian Oudard
3
wie kann man dann "this ia string" [:: - 1] besser schreiben? umgekehrt scheint nicht zu helfen
Berry Tsakala
24
Das Problem mit reverse () besteht darin, dass ein Iterator zurückgegeben wird. Wenn Sie also den Typ der umgekehrten Sequenz (Tupel, Zeichenfolge, Liste, Unicode, Benutzertypen ...) beibehalten möchten, benötigen Sie einen zusätzlichen Schritt, um sie zurück zu konvertieren .
Rafał Dowgird
6
def reverse_string (string): return string [:: - 1]
pi.
4
@pi Ich denke, wenn man genug weiß, um reverse_string so zu definieren, wie man es hat, kann man das [:: - 1] in seinem Code belassen und sich mit seiner Bedeutung und dem Gefühl, dass es angemessen ist, wohl fühlen.
Physikmichael
289

Dekorateure

Mit Dekorateuren können Sie eine Funktion oder Methode in eine andere Funktion einbinden, die Funktionen hinzufügen, Argumente oder Ergebnisse ändern usw. Sie schreiben Dekorateure eine Zeile über der Funktionsdefinition, beginnend mit einem "at" -Zeichen (@).

Das Beispiel zeigt einen print_argsDekorateur, der die Argumente der dekorierten Funktion druckt, bevor er sie aufruft:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo
DzinX
quelle
54
Bei der Definition von Dekoratoren würde ich empfehlen, den Dekorator mit @decorator zu dekorieren. Es wird ein Dekorateur erstellt, der bei der Selbstbeobachtung eine Funktionssignatur beibehält. Weitere Infos hier: phyast.pitt.edu/~micheles/python/documentation.html
sirwart
45
Wie ist das eine versteckte Funktion?
Vetle
50
Nun, es ist in den meisten einfachen Python-Tutorials nicht vorhanden, und ich bin lange darauf gestoßen, nachdem ich angefangen habe, Python zu verwenden. Das würde ich als verstecktes Feature bezeichnen, genau wie bei anderen Top-Posts hier.
DzinX
16
Vetler, die Fragen fragen nach "weniger bekannten, aber nützlichen Funktionen der Python-Programmiersprache". Wie messen Sie weniger bekannte, aber nützliche Funktionen? Ich meine, wie sind diese Antworten versteckte Funktionen?
Johnd
4
@vetler Die meisten Dinge hier sind kaum "versteckt".
Humphrey Bogart
288

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")
rlerallut
quelle
218
Ich denke, die for / else-Syntax ist umständlich. Es "fühlt" sich an, als ob die else-Klausel ausgeführt werden sollte, wenn der Hauptteil der Schleife niemals ausgeführt wird.
Codeape
14
Ah. Hab das noch nie gesehen! Aber ich muss sagen, es ist ein bisschen eine Fehlbezeichnung. Wer würde erwarten, dass der else-Block nur ausgeführt wird, wenn break dies niemals tut? Ich stimme Codeape zu: Es sieht so aus, als wäre sonst für leere Foos eingetragen.
Daren Thomas
52
scheint wie das Schlüsselwort sollte endlich sein, nicht anders
Jiaaro
21
Außer schließlich wird bereits so verwendet, dass diese Suite immer ausgeführt wird.
7
Sollte definitiv nicht "sonst" sein. Vielleicht 'dann' oder so und dann 'sonst', wenn die Schleife nie ausgeführt wurde.
Tor Valamo
258

Ab 2.5 haben Diktate eine spezielle Methode __missing__, die für fehlende Gegenstände 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 diktierte Unterklasse in collectionsaufgerufen defaultdict, die fast 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 Diktate in reguläre Diktate umzuwandeln, bevor Sie sie an Funktionen übergeben, die solche Unterklassen nicht erwarten. Viele Codes verwenden d[a_key]und fangen KeyErrors, um zu überprüfen, ob ein Element vorhanden ist, das dem Diktat ein neues Element hinzufügen würde.

Armin Ronacher
quelle
10
Ich bevorzuge die Verwendung von setdefault. m = {}; m.setdefault ('foo', 1)
Grayger
22
@grayger meinte das m={}; m.setdefault('foo', []).append(1).
Cristian Ciupitu
1
Es gibt jedoch Fälle, in denen das Übergeben des Standarddikts sehr praktisch ist. Die Funktion kann beispielsweise über den Wert iterieren und funktioniert für undefinierte Schlüssel ohne zusätzlichen Code, da die Standardeinstellung eine leere Liste ist.
Marian
3
defaultdict ist unter bestimmten Umständen besser als setdefault, da das Standardobjekt nur erstellt wird, wenn der Schlüssel fehlt. setdefault erstellt es, ob es fehlt oder nicht. Wenn die Erstellung Ihres Standardobjekts teuer ist, kann dies ein Leistungseinbruch sein. Ich habe eine anständige Beschleunigung eines Programms erzielt, indem ich einfach alle setdefault-Aufrufe geändert habe.
Whatang
2
defaultdictist auch leistungsfähiger als die setdefaultMethode in anderen Fällen. Zum Beispiel für eine Gegen dd = collections.defaultdict(int) ... dd[k] += 1vs d.setdefault(k, 0) += 1.
Mike Graham
247

In-Place-Wertetausch

>>> 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 erstellt. Die linke Seite der Zuweisung entpackt sofort das (nicht referenzierte) Tupel zu den Namen aund b.

Nach der Zuweisung wird das neue Tupel nicht referenziert und für die Speicherbereinigung markiert, und die Werte sind an gebunden aund bwurden ausgetauscht.

Wie im Python-Tutorial zu Datenstrukturen erwähnt ,

Beachten Sie, dass die Mehrfachzuweisung eigentlich nur eine Kombination aus Tupelpacken und Sequenzentpacken ist.

Lucas S.
quelle
1
Verwendet dies mehr realen Speicher als auf herkömmliche Weise? Ich würde es tun, da Sie ein Tupel erstellen, anstatt nur eine Swap-Variable
Nathan
75
Es wird nicht mehr Speicher benötigt. Es verbraucht weniger. Ich habe es nur in beide Richtungen geschrieben und den Bytecode dekompiliert. Der Compiler optimiert, wie Sie es sich erhoffen würden. Die Ergebnisse zeigten, dass die Vars und dann ROT_TWOing eingerichtet wurden. ROT_TWO bedeutet "die beiden obersten Stapelvariablen tauschen" ... Eigentlich ziemlich schick.
Royal
5
Sie weisen auch versehentlich auf eine weitere nette Funktion von Python hin, nämlich dass Sie implizit ein Tupel von Elementen erstellen können, indem Sie sie durch Kommas trennen.
Asmeurer
3
Dana the Sane: Zuweisung in Python ist eine Anweisung, kein Ausdruck, so dass dieser Ausdruck ungültig wäre, wenn = eine höhere Priorität hätte (dh er wurde als a, (b = b), a) interpretiert.
hbn
5
Dies ist die am wenigsten versteckte Funktion, die ich hier gelesen habe. Schön, aber in jedem Python-Tutorial explizit beschrieben.
Thiago Chaves
235

Lesbare reguläre Ausdrücke

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

Beispiel für eine ausführliche Syntax (von Dive 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 Namensnamenübereinstimmungen (aus dem HOWTO für reguläre Ausdrücke )

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

re.VERBOSEDank der Verkettung von Zeichenfolgenliteralen können Sie auch einen regulären Ausdruck ohne Verwendung ausführlich schreiben .

>>> 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})$"
18044
quelle
7
Ich weiß nicht, ob ich das wirklich als Python-Funktion betrachten würde. Die meisten RE-Engines haben eine ausführliche Option.
Jeremy Banks
18
Ja, aber weil Sie es nicht in grep oder in den meisten Editoren tun können, wissen viele Leute nicht, dass es da ist. Die Tatsache, dass andere Sprachen ein gleichwertiges Feature haben, macht es nicht zu einem nützlichen und wenig bekannten Feature von Python
Mark Baker
7
In einem großen Projekt mit vielen optimierten regulären Ausdrücken (sprich: optimiert für Maschinen, aber nicht für Menschen) habe ich die Kugel gebissen und alle in eine ausführliche Syntax konvertiert. Jetzt ist es viel einfacher, neue Entwickler in Projekte einzuführen. Von nun an erzwingen wir ausführliche REs für jedes Projekt.
Berk D. Demir
Ich würde lieber einfach sagen: Hunderte = "(CM | CD | D? C {0,3})" # 900 (CM), 400 (CD) usw. Die Sprache hat bereits eine Möglichkeit, Dingen Namen zu geben, a Möglichkeit, Kommentare hinzuzufügen und Zeichenfolgen zu kombinieren. Warum hier eine spezielle Bibliothekssyntax für Dinge verwenden, die die Sprache bereits perfekt macht? Es scheint direkt gegen Perlis 'Epigramm 9 zu gehen.
Ken
3
@ Ken: Ein regulärer Ausdruck befindet sich möglicherweise nicht immer direkt in der Quelle, er kann aus Einstellungen oder einer Konfigurationsdatei gelesen werden. Das Zulassen von Kommentaren oder nur zusätzlichen Leerzeichen (zur besseren Lesbarkeit) kann eine große Hilfe sein.
222

Entpacken des Funktionsarguments

Sie können eine Liste oder ein Wörterbuch als Funktionsargumente mit *und entpacken **.

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 Verknüpfung, da Listen, Tupel und Diktate häufig als Container verwendet werden.

E-Satis
quelle
27
* ist auch als Splat-Operator bekannt
Gabriel
3
Ich mag diese Funktion, aber Pylint tut das leider nicht.
Stephen Paulger
5
Pylints Rat ist kein Gesetz. Die andere Methode, apply (callable, arg_seq, arg_map), ist seit 2.3 veraltet.
Yann Vernier
1
Pylints Rat ist vielleicht kein Gesetz, aber es ist verdammt guter Rat. Das Debuggen von Code, der sich solchen Dingen übermäßig hingibt, ist die Hölle. Wie das Originalplakat feststellt, ist dies eine nützliche Verknüpfung .
Andrew
2
Ich habe gesehen, dass dies einmal im Code verwendet wurde, und mich gefragt, was es getan hat. Leider ist es schwer, nach "Python **" zu googeln
Fraser Graham
205

ROT13 ist eine gültige Codierung für den Quellcode, wenn Sie die richtige Codierungsdeklaration oben in der Codedatei verwenden:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
André
quelle
10
Großartig! Beachten Sie, wie Byte-Strings wörtlich genommen werden, Unicode-Strings jedoch decodiert werden: trycevag h"Uryyb fgnpxbiresybj!"
u0b34a0f6ae
12
leider ist es von py3k entfernt
mykhal
9
Dies ist gut, um Antivirus zu umgehen.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
96
Das hat nichts mit der Codierung zu tun, es ist nur Python, das auf Walisisch geschrieben ist. :-P
Olivier Verdier
33
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
Manuel Ferreria
183

Erstellen Sie neue Typen auf voll dynamische Weise

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

das ist genau das gleiche wie

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

Wahrscheinlich nicht das Nützlichste, aber schön zu wissen.

Bearbeiten : Der feste Name des neuen Typs sollte NewTypegenau so sein wie bei der classAnweisung.

Bearbeiten : Der Titel wurde angepasst, um die Funktion genauer zu beschreiben.

Torsten Marek
quelle
8
Dies hat viel Potenzial für Nützlichkeit, z. B. JIT ORMs
Mark Cidade
8
Ich verwende es, um HTML-Form-Klassen basierend auf einer dynamischen Eingabe zu generieren. Sehr schön!
pi.
15
Hinweis: Alle Klassen werden zur Laufzeit erstellt. Sie können die Anweisung 'class' also innerhalb einer Bedingung oder innerhalb einer Funktion verwenden (sehr nützlich, um Familien von Klassen oder Klassen zu erstellen, die als Abschlüsse fungieren). Die Verbesserung, die 'Typ' bringt, ist die Fähigkeit, einen dynamisch generierten Satz von Attributen (oder Basen) sauber zu definieren.
Spookylukey
1
Sie können auch anonyme Typen mit einer leeren Zeichenfolge erstellen, z.
B
3
Könnte für Code-Injektionen sehr nützlich sein.
Avihu Turzion
179

Kontextmanager und die withAnweisung " "

Eingeführt im PEP 343 , ein Kontext - Manager ist ein Objekt , das für eine Reihe von Aussagen , die als Laufzeitkontext wirkt.

Da die Funktion neue Schlüsselwörter verwendet, wird sie schrittweise eingeführt: Sie ist in Python 2.5 über die __future__Direktive verfügbar . Python 2.6 und höher (einschließlich Python 3) ist standardmäßig verfügbar.

Ich habe die "with" -Anweisung oft verwendet, weil ich denke, dass es ein sehr nützliches Konstrukt ist. Hier ist eine kurze Demo:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

Was hier hinter den Kulissen passiert, ist, dass die Anweisung "with" das Special __enter__und die __exit__Methoden für das Dateiobjekt aufruft . Ausnahmedetails werden auch an übergeben, __exit__wenn eine Ausnahme aus dem with-Anweisungshauptteil ausgelöst wurde, sodass dort eine Ausnahmebehandlung stattfinden kann.

In diesem speziellen Fall bedeutet dies für Sie, dass die Datei geschlossen wird, wenn die Ausführung außerhalb des Bereichs der withSuite liegt, unabhängig davon, ob dies normal erfolgt oder ob eine Ausnahme ausgelöst wurde. Dies ist im Grunde eine Möglichkeit, allgemeinen Code für die Ausnahmebehandlung zu abstrahieren.

Andere häufige Anwendungsfälle hierfür sind das Sperren mit Threads und Datenbanktransaktionen.

Ycros
quelle
3
Ich würde eine Codeüberprüfung nicht genehmigen, die etwas aus der Zukunft importiert . Die Funktionen sind eher niedlich als nützlich, und normalerweise verwirren sie Python-Neulinge.
Ein bezahlter Nerd
6
Ja, solche "niedlichen" Funktionen wie verschachtelte Bereiche und Generatoren sollten besser denen überlassen werden, die wissen, was sie tun. Und jeder, der mit zukünftigen Versionen von Python kompatibel sein möchte. Für verschachtelte Bereiche und Generatoren bedeutet "zukünftige Versionen" von Python 2.2 bzw. 2.5. Für die with-Anweisung bedeutet "zukünftige Versionen" von Python 2.6.
Chris B.
10
Dies mag selbstverständlich sein, aber mit Python v2.6 + müssen Sie nicht mehr aus der Zukunft importieren . with ist jetzt ein erstklassiges Schlüsselwort.
Fitzgeraldsteele
25
In 2.7 können Sie mehrere haben withs:) with open('filea') as filea and open('fileb') as fileb: ...
Austin Richardson
5
@Austin Ich konnte diese Syntax nicht für 2.7 verwenden. Dies funktionierte jedoch: with open('filea') as filea, open('fileb') as fileb: ...
wim
168

Wörterbücher haben eine get () -Methode

Wörterbücher haben eine 'get ()' - Methode. Wenn Sie d ['key'] ausführen und key nicht vorhanden ist, erhalten Sie eine Ausnahme. Wenn Sie d.get ('key') ausführen, erhalten Sie None zurück, wenn 'key' nicht vorhanden ist. Sie können ein zweites Argument hinzufügen, um dieses Element anstelle von "Keine" zurückzugewinnen, z. B.: D.get ('Schlüssel', 0).

Es ist großartig für Dinge wie das Addieren von Zahlen:

sum[value] = sum.get(value, 0) + 1

Rory
quelle
39
Überprüfen Sie auch die setdefault-Methode.
Daren Thomas
27
Überprüfen Sie auch die collection.defaultdict-Klasse.
JFS
8
Wenn Sie Python 2.7 oder höher oder 3.1 oder höher verwenden, überprüfen Sie die Counter-Klasse im Sammlungsmodul. docs.python.org/library/collections.html#collections.Counter
Elias Zamaria
Oh Mann, die ganze Zeit habe ich getan get(key, None). Hatte keine Ahnung, dass Nonestandardmäßig zur Verfügung gestellt wurde.
Jordan Reiter
152

Deskriptoren

Sie sind die Magie hinter einer ganzen Reihe von Python-Kernfunktionen.

Wenn Sie einen gepunkteten Zugriff verwenden, um ein Mitglied (z. B. xy) nachzuschlagen, sucht Python zuerst nach dem Mitglied im Instanzwörterbuch. Wenn es nicht gefunden wird, sucht es im Klassenwörterbuch danach. Wenn es im Klassenwörterbuch gefunden wird und das Objekt das Deskriptorprotokoll implementiert, führt Python es aus, anstatt es nur zurückzugeben. Ein Deskriptor ist jede Klasse , die die Geräte __get__, __set__oder __delete__Methoden.

So implementieren Sie Ihre eigene (schreibgeschützte) Version der Eigenschaft mithilfe von Deskriptoren:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

und Sie würden es genau wie die eingebaute Eigenschaft () verwenden:

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

Deskriptoren werden in Python verwendet, um unter anderem Eigenschaften, gebundene Methoden, statische Methoden, Klassenmethoden und Slots zu implementieren. Wenn man sie versteht, kann man leicht erkennen, warum viele Dinge, die früher wie Python-Macken aussahen, so sind, wie sie sind.

Raymond Hettinger hat ein exzellentes Tutorial , das sie viel besser beschreibt als ich.

Nick Johnson
quelle
Dies ist ein Duplikat von Dekorateuren, nicht wahr? ( stackoverflow.com/questions/101268/… )
Gecco
2
Nein, Dekoratoren und Deskriptoren sind völlig verschiedene Dinge, obwohl ich im Beispielcode einen Deskriptor-Dekorator erstelle. :)
Nick Johnson
1
Der andere Weg, dies zu tun, ist mit einem Lambda:foo = property(lambda self: self.__foo)
Pete Peterson
1
@PetePeterson Ja, aber propertyselbst wird mit Deskriptoren implementiert, was der Punkt meines Beitrags war.
Nick Johnson
142

Bedingte Zuordnung

x = 3 if (y == 1) else 2

Es macht genau das, wonach es sich anhört: "Weisen Sie x 3 zu, wenn y 1 ist, andernfalls weisen Sie x 2 zu". Beachten Sie, dass die Parens nicht notwendig sind, aber ich mag sie für die Lesbarkeit. Sie können es auch verketten, wenn Sie etwas Komplizierteres haben:

x = 3 if (y == 1) else 2 if (y == -1) else 1

Ab einem bestimmten Punkt geht es allerdings etwas zu weit.

Beachten Sie, dass Sie if ... else in einem beliebigen Ausdruck verwenden können. Zum Beispiel:

(func1 if y == 1 else func2)(arg1, arg2) 

Hier wird func1 aufgerufen, wenn y 1 ist, andernfalls func2. In beiden Fällen wird die entsprechende Funktion mit den Argumenten arg1 und arg2 aufgerufen.

Analog gilt auch:

x = (class1 if y == 1 else class2)(arg1, arg2)

Dabei sind Klasse1 und Klasse2 zwei Klassen.

tghw
quelle
29
Die Zuordnung ist nicht der besondere Teil. Sie könnten genauso gut etwas tun wie: 3 zurückgeben, wenn (y == 1) sonst 2.
Brian
25
Dieser alternative Weg ist das erste Mal, dass ich verschleiertes Python sehe.
Craig McQueen
3
Kylebrooks: In diesem Fall schließen boolesche Operatoren nicht kurz. Es wird nur 2 ausgewertet, wenn bool (3) == False ist.
RoadieRich
15
Diese rückwärts gerichtete Codierung verwirrt mich. so etwas x = ((y == 1) ? 3 : 2)macht für mich mehr Sinn
mpen
13
Ich bin der Meinung, dass genau das Gegenteil von @Mark ist. Ternäre Operatoren im C-Stil haben mich immer verwirrt. Ist die rechte Seite oder die Mitte das, was unter falschen Bedingungen bewertet wird? Ich bevorzuge die ternäre Syntax von Python.
Jeffrey Harris
141

Doctest : Dokumentation und Unit-Test gleichzeitig.

Beispiel aus der Python-Dokumentation:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()
Pierre-Jean Coudert
quelle
6
Doctests sind sicherlich cool, aber ich mag wirklich nicht alle Cruft, die Sie eingeben müssen, um zu testen, ob etwas eine Ausnahme auslösen sollte
TM.
60
Doctests werden überbewertet und verschmutzen die Dokumentation. Wie oft testen Sie eine eigenständige Funktion ohne setUp ()?
Ein bezahlter Nerd
2
Wer sagt, dass Sie sich nicht in einem Doctest einrichten können? Schreiben Sie eine Funktion, die den Kontext generiert und locals()dann in Ihrem Doctest do locals().update(setUp())= D
Jiaaro
12
Wenn für eine eigenständige Funktion ein SetUp erforderlich ist, besteht eine hohe Wahrscheinlichkeit, dass sie von nicht verwandten Elementen entkoppelt oder in eine Klasse eingeordnet wird. Der Class-Doctest-Namespace kann dann in Class-Method-Doctests wiederverwendet werden. Es ist also ein bisschen wie setUp, nur DRY und lesbar.
Andy Mikhaylenko
4
"Wie oft testen Sie eine eigenständige Funktion" - viele. Ich finde, dass Doctests oft auf natürliche Weise aus dem Designprozess hervorgehen, wenn ich mich für Fassaden entscheide.
Gregg Lind
138

Benannte Formatierung

Die% -Formatierung erfordert ein Wörterbuch (gilt auch für die Validierung von% i /% s usw.).

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

Und da local () auch ein Wörterbuch ist, können Sie dies einfach als Diktat übergeben und% -substitions aus Ihren lokalen Variablen haben. Ich denke, das ist verpönt, vereinfacht aber die Dinge.

Neue Stilformatierung

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
Pasi Savolainen
quelle
60
Wird auslaufen und schließlich durch die format () -Methode des Strings ersetzt.
Constantin
3
Die benannte Formatierung ist für Übersetzer sehr nützlich, da sie in der Regel nur die
Formatzeichenfolge
2
Scheint in Python 3.0.1 zu funktionieren (erforderlich, um Elternthesen rund um den Druckaufruf hinzuzufügen).
Pasi Savolainen
9
ein Hasch , nicht wahr? Ich sehe, woher du kommst.
Shylent
11
Die Formatierung von% s wird nicht auslaufen. str.format () ist sicherlich pythonischer, ist jedoch für das einfache Ersetzen von Strings 10x langsamer. Meiner Meinung nach ist die Formatierung von% immer noch eine bewährte Methode.
Kenneth Reitz
132

Um weitere Python-Module hinzuzufügen (insbesondere solche von Drittanbietern), scheinen die meisten Benutzer PYTHONPATH-Umgebungsvariablen zu verwenden, oder sie fügen Symlinks oder Verzeichnisse in ihre Site-Package-Verzeichnisse ein. Eine andere Möglichkeit ist die Verwendung von * .pth-Dateien. Hier ist die Erklärung des offiziellen Python-Dokuments:

"Der bequemste Weg [um den Suchpfad von Python zu ändern] besteht darin, eine Pfadkonfigurationsdatei zu einem Verzeichnis hinzuzufügen, das sich bereits im Python-Pfad befindet, normalerweise zum Verzeichnis ... / site-packages /. Pfadkonfigurationsdateien haben die Erweiterung .pth und jede Zeile muss einen einzelnen Pfad enthalten, der an sys.path angehängt wird. (Da die neuen Pfade an sys.path angehängt werden, überschreiben Module in den hinzugefügten Verzeichnissen Standardmodule nicht. Dies bedeutet, dass Sie diesen Mechanismus nicht verwenden können zum Installieren fester Versionen von Standardmodulen.) "

dgrant
quelle
1
Ich habe nie die Verbindung zwischen dieser .pth-Datei im Verzeichnis site-packages von setuptools und dieser Idee hergestellt. genial.
Dave Paola
122

Ausnahme sonst Klausel:

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

Die Verwendung der else-Klausel ist besser als das Hinzufügen von zusätzlichem Code zur try-Klausel, da dadurch vermieden wird, dass versehentlich eine Ausnahme abgefangen wird, die nicht durch den durch die try ... außer -Anweisung geschützten Code ausgelöst wurde.

Siehe http://docs.python.org/tut/node10.html

Constantin
quelle
8
+1 das ist großartig. Wenn der try-Block ausgeführt wird, ohne Ausnahmeblöcke einzugeben, wird der else-Block eingegeben. Und dann wird natürlich der finally-Block ausgeführt
inspectorG4dget
Ich verstehe endlich, warum das "Sonst" da ist! Vielen Dank.
Taynaron
Es wäre sinnvoller, fortzufahren, aber ich denke, es ist bereits vergeben;)
Paweł Prażak
Beachten Sie, dass Sie in älteren Versionen von Python2 nicht beide haben können: und schließlich: Klauseln für denselben Versuch: block
Kevin Horn
1
@ Paweł Prażak, wie Kevin Horn erwähnte, wurde diese Syntax nach der ersten Veröffentlichung von Python eingeführt, und das Hinzufügen neuer reservierter Schlüsselwörter zur vorhandenen Sprache ist immer problematisch. Aus diesem Grund wird ein vorhandenes Schlüsselwort normalerweise wiederverwendet (siehe "auto" im aktuellen C ++ - Standard).
Constantin
114

Ausnahmen erneut erheben :

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

Die Anweisung 'raise' ohne Argumente in einem Fehlerhandler weist Python an, die Ausnahme mit intaktem ursprünglichen Traceback erneut auszulösen , sodass Sie sagen können: "Oh, sorry, sorry, ich wollte das nicht abfangen, sorry, sorry. ""

Wenn Sie den ursprünglichen Traceback drucken, speichern oder damit experimentieren möchten, können Sie ihn mit sys.exc_info () abrufen. Der Druckvorgang erfolgt wie in Python mit dem Traceback-Modul.

Thomas Wouters
quelle
Entschuldigung, aber dies ist eine bekannte und gemeinsame Funktion fast aller Sprachen.
Lucas S.
6
Beachten Sie den kursiven Text. Einige Leute tun dies raise estattdessen, wodurch der ursprüngliche Traceback nicht erhalten bleibt.
Hablabit
12
Vielleicht magischer, exc_info = sys.exc_info(); raise exc_info[0], exc_info[1], exc_info[2]ist gleichbedeutend damit, aber Sie können diese Werte ändern (z. B. den Ausnahmetyp oder die Nachricht ändern)
ianb
3
@ Lucas S. Nun, ich wusste es nicht und ich bin froh, dass es hier geschrieben steht.
E-Satis
Ich kann meine Jugend hier zeigen, aber ich habe immer die Python 3-Syntax in Python 2.7 ohne
Probleme verwendet
106

Hauptnachrichten :)

import this
# btw look at this module's source :)

Entschlüsselt :

Das Zen von Python von Tim Peters

Schön ist besser als hässlich.
Explizit ist besser als implizit.
Einfach ist besser als komplex.
Komplex ist besser als kompliziert.
Wohnung ist besser als verschachtelt.
Spärlich ist besser als dicht.
Lesbarkeit zählt.
Sonderfälle sind nicht speziell genug, um gegen die Regeln zu verstoßen.
Obwohl Praktikabilität die Reinheit übertrifft.
Fehler sollten niemals stillschweigend vergehen.
Sofern nicht ausdrücklich zum Schweigen gebracht.
Verweigern Sie angesichts von Zweideutigkeiten die Versuchung zu raten. Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun.
Obwohl dieser Weg zunächst vielleicht nicht offensichtlich ist, es sei denn, Sie sind Niederländer.
Jetzt ist besser als nie.
Obwohl nie oft besser ist alsgerade jetzt.
Wenn die Implementierung schwer zu erklären ist, ist es eine schlechte Idee.
Wenn die Implementierung leicht zu erklären ist, kann dies eine gute Idee sein.
Namespaces sind eine großartige Idee - lasst uns mehr davon machen!

Mark
quelle
1
Irgendeine Idee, warum die Quelle so verschlüsselt wurde? War es nur zum Spaß oder gab es einen anderen Grund?
MiniQuark
42
Die Art und Weise, wie die Quelle geschrieben ist, widerspricht dem Zen!
hasen
2
Ich habe meine /usr/lib/python2.6/this.py aktualisiert und den alten Code durch diesen ersetzt. print s.translate("".join(chr(64<i<91 and 65+(i-52)%26 or 96<i<123 and 97+(i-84)%26 or i) for i in range(256)))Jetzt sieht es viel besser aus !! :-D
fortran
2
@MiniQuark: kurze Geschichtsstunde: wefearchange.org/2010/06/import-this-and-zen-of-python.html
105

Vervollständigung der Registerkarte Interaktiver Interpreter

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

Sie müssen auch eine PYTHONSTARTUP-Umgebungsvariable festlegen.

mjard
quelle
2
Dies ist eine sehr nützliche Funktion. So sehr, dass ich ein einfaches Skript habe, um es zu aktivieren (plus ein paar andere Verbesserungen der Selbstbeobachtung): pixelbeat.org/scripts/inpy
pixelbeat
43
IPython gibt Ihnen dieses Plus Tonnen von anderen netten Sachen
Akaihola
Dies wäre an der pdb-Eingabeaufforderung nützlicher gewesen als an der regulären Python-Eingabeaufforderung (da IPython diesen Zweck sowieso erfüllt). Dies scheint jedoch an der pdb-Eingabeaufforderung nicht zu funktionieren, wahrscheinlich weil pdb seine eigene for-Registerkarte bindet (was weniger nützlich ist). Ich habe versucht, parse_and_bind () an der pdb-Eingabeaufforderung aufzurufen, aber es hat immer noch nicht funktioniert. Die Alternative, mit IPython eine pdb-Eingabeaufforderung zu erhalten, ist mehr Arbeit, daher verwende ich sie eher nicht.
Haridsv
2
@haridsv - easy_install ipdb- dann können Sie verwendenimport ipdb; ipdb.set_trace()
Doug Harris
1
Auf osx [und ich stelle mir andere Systeme vor, die libedit verwenden] müssen Sie tunreadline.parse_and_bind ("bind ^I rl_complete")
Foo Bah
91

Verschachtelte Listenverständnisse und Generatorausdrücke:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

Diese können große Teile des Nested-Loop-Codes ersetzen.

Rafał Dowgird
quelle
"für j in Bereich (i)" - ist das ein Tippfehler? Normalerweise möchten Sie feste Bereiche für i und j. Wenn Sie auf ein 2D-Array zugreifen, werden Sie die Hälfte Ihrer Elemente verpassen.
Peter Gibson
In diesem Beispiel greife ich nicht auf Arrays zu. Der einzige Zweck dieses Codes besteht darin, zu zeigen, dass die Ausdrücke aus den inneren Bereichen auf die Ausdrücke aus den äußeren zugreifen können. Das Nebenprodukt ist eine Liste von Paaren (x, y), so dass 4> x> y> 0 ist.
Rafał Dowgird
2
sorta wie doppelte Integration in die Analysis oder doppelte Summation.
Yoo
22
Der wichtigste Punkt, an den ich mich erinnern sollte (was mich lange Zeit gekostet hat), ist, dass die Reihenfolge der forAnweisungen in der Reihenfolge geschrieben werden muss, in der Sie erwarten würden, dass sie in einer Standard-for-Schleife von außen nach innen geschrieben werden.
Sykora
2
Um Sykoras Kommentar zu ergänzen: Stellen Sie sich vor, Sie beginnen mit einem Stapel von fors und ifs mit yield xinnen. Um dies in einen Generatorausdruck umzuwandeln, verschieben Sie xzuerst, löschen Sie alle Doppelpunkte (und die yield) und umgeben Sie das Ganze in Klammern. Um stattdessen ein Listenverständnis zu erhalten, ersetzen Sie die äußeren Parens durch eckige Klammern.
Ken Arnold
91

Überlastung des setBedieners für das eingebaute Gerät:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

Weitere Details finden Sie in der Standardbibliotheksreferenz: Set Types

Kiv
quelle