Welche allgemeinen Tipps haben Sie zum Golfen in Python? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme anwenden lassen und die zumindest etwas spezifisch für Python sind (z. B. "Kommentare entfernen" ist keine Antwort).
Bitte posten Sie einen Tipp pro Antwort.
Antworten:
Verwenden Sie
a=b=c=0
anstelle vona,b,c=0,0,0
.Verwenden Sie
a,b,c='123'
anstelle vona,b,c='1','2','3'
.quelle
Bedingungen können langwierig sein. In einigen Fällen können Sie eine einfache Bedingung durch ersetzen
(a,b)[condition]
. Wenn diescondition
zutrifft,b
wird zurückgegeben.Vergleichen Sie
Dazu
quelle
a if a<b else b
unda<b and a or b
(lambda(): b, lambda(): a)[a < b]()
Machen Sie Ihren eigenen Kurzschluss mit LambdasP and A or B
an ein A, das gibtbool(A)=False
. Aber(P and [A] or [B])[0]
werde den Job machen. Siehe diveintopython.net/power_of_introspection/and_or.html als Referenz.Eine großartige Sache, die ich einmal gemacht habe, ist:
Anstatt von:
Pythons Vergleichsoperatoren rocken.
Wenn in Python 2 alles vergleichbar ist, können Sie auf
and
diese Weise auch den Operator umgehen . Wenn zum Beispiela
,b
,c
undd
ganze Zahlen sind,kann um ein Zeichen gekürzt werden, um:
Dabei ist jede Liste größer als eine ganze Zahl.
Wenn
c
undd
sind Listen, wird dies noch besser:quelle
3>a>1<b<5
[$a => $b]->[$b <= $a]
:)if(a<b)+(c>d):foo()
*
. Einor
würde sein+
foo()if 3>a>1<b<5
Wenn Sie eine integrierte Funktion wiederholt verwenden, ist es möglicherweise platzsparender, wenn Sie einen neuen Namen vergeben, wenn Sie andere Argumente verwenden:
quelle
Manchmal erfordert Ihr Python-Code zwei Einrückungsstufen. Es ist naheliegend, für jede Einrückungsstufe ein und zwei Leerzeichen zu verwenden.
Python 2 betrachtet die Tabulator- und Leerzeichen jedoch als unterschiedliche Einrückungsstufen.
Dies bedeutet, dass die erste Einrückungsstufe ein Leerzeichen und die zweite ein Tabulatorzeichen sein kann.
Zum Beispiel:
Wo
\t
ist das Tabulatorzeichen?quelle
TabError: inconsistent use of tabs and spaces in indentation.
Verwenden Sie die Zeichenfolgensubstitution und verwenden Sie
exec
lange Schlüsselwörterlambda
, die in Ihrem Code häufig vorkommen.Die Zielzeichenfolge ist sehr häufig
'lambda '
und 7 Byte lang. Angenommen, Ihr Code-Snippet enthältn
Vorkommen von'lambda '
und ists
bytelang. Dann:plain
Option ists
bytelang.replace
Option ists - 6n + 29
bytelang.%
Option ists - 5n + 22 + len(str(n))
bytelang.Aus einer Darstellung von Bytes, die
plain
für diese drei Optionen gespeichert wurden , können wir Folgendes ersehen:exec"..."%(('lambda ',)*5)
2 Bytes gespart, und dies ist die beste Option.exec"...".replace('`','lambda ')
die beste Option.In anderen Fällen können Sie die folgende Tabelle indizieren:
Wenn die Zeichenfolge
lambda x,y:
(Länge 11) beispielsweise dreimal in Ihrem Code vorkommt, sollten Sie besser schreibenexec"..."%(('lambda x,y:',)*3)
.quelle
replace
sind riesig.=>
nur die Zeichenfolge= lambda
. Zum Beispielf=>:0
wäref = lambda: 0
.Verwenden Sie Extended Slicing, um eine Zeichenfolge aus vielen auszuwählen
vs
In diesem booleschen 2-String-Fall kann man auch schreiben
zum
Im Gegensatz zum Interleaving funktioniert dies für Zeichenfolgen beliebiger Länge, es können jedoch Probleme mit der Operatorpriorität auftreten, wenn
b
es sich stattdessen um einen Ausdruck handelt.quelle
for x in ("foo","bar","baz"): print x
x
gerendert werden. Der Golf-Teil ist der"fbboaaorz"[x::3]
vs["foo","bar","baz"][x]
Wie derx
Wert abgeleitet wird, wäre ein weiterer Teil Ihrer Golflösung .Verwenden Sie
`n`
diese Option , um eine Ganzzahl in eine Zeichenfolge zu konvertieren, anstatt Folgendes zu verwendenstr(n)
:quelle
Speichern Sie Nachschlagetabellen als magische Zahlen
Angenommen, Sie möchten eine Boolesche Nachschlagetabelle fest codieren, z. B. welche der ersten zwölf englischen Zahlen eine enthält
n
.Dann können Sie diese Nachschlagetabelle kurz und bündig implementieren als:
mit dem resultierenden
0
oder1
gleich zuFalse
seinTrue
.Die Idee ist, dass die magische Zahl die Tabelle als Bitstring
bin(3714)
= speichert0b111010000010
, wobei dien
-te Ziffer (vom Ende) demn
Eintrag in der th-Tabelle entspricht. Wir greifen auf denn
dritten Eintrag zu, indem wir die Ziffernfeldern
nach rechts verschieben und die letzte Ziffer um nehmen&1
.Diese Speichermethode ist sehr effizient. Vergleichen Sie mit den Alternativen
Sie können Ihre Nachschlagetabelle Multibit-Einträge speichern lassen, die wie folgt extrahiert werden können
um den relevanten 4-Bit-Block zu extrahieren.
quelle
Reduzieren Sie zwei numerische Schleifen zu einer
Angenommen, Sie iterieren über die Zellen eines
m*n
Gitters. Anstelle von zwei verschachteltenfor
Schleifen, eine für die Zeile und eine für die Spalte, ist es normalerweise kürzer, eine einzelne Schleife zu verwenden, um über diem*n
Zellen des Rasters zu iterieren . Sie können die Zeile und Spalte der Zelle in der Schleife extrahieren.Originalcode:
Golf Code:
Tatsächlich iterieren Sie über das kartesische Produkt der beiden Bereiche und codieren das Paar
(i,j)
alsx=i*n+j
. Sie sparen sich einen teurenrange
Anruf und eine gewisse Einrückung in der Schleife. Die Reihenfolge der Iteration bleibt unverändert.Verwenden Sie
//
statt/
in Python 3. Wenn Sie bezieheni
undj
viele Male, kann es schneller sein , ihre Werte zuweiseni=k/n
,j=k%n
innerhalb der Schleife.quelle
for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o)
n
Schleifen: repl.it/EHwaitertools.product
kann dies sehr viel präziser sein als verschachtelte Schleifen, insbesondere beim Generieren kartesischer Produkte.a1, a2, b1, b2
sind Beispiele für das kartesische Produkt von'ab'
und'12'
Es sei denn, das folgende Token beginnt mit
e
oderE
. Sie können das Leerzeichen nach einer Zahl entfernen.Zum Beispiel:
Wird:
Wenn Sie dies in komplizierten einzeiligen Anweisungen verwenden, können einige Zeichen gespart werden.
BEARBEITEN: wie @marcog hervorhob,
4or a
wird funktionieren, aber nicht,a or4
da dies mit einem Variablennamen verwechselt wird.quelle
if(i,j)==(4,4):
ist noch kürzer und in diesem Sonderfallif i==j==4:
4or a
funktioniert, aber nichta or4
0or
funktioniert auch nicht (0o
ist ein Präfix für Oktalzahlen).0 or x
wird immer wieder zurückx
. Könnte auch das ausschneiden0 or
.0or
ist aber in Ordnung als Teil einer längeren Nummer.10 or x
ist äquivalent zu10or x
.Für eine Ganzzahl
n
können Sie schreibenn+1
wie-~n
n-1
wie~-n
weil das Bit Flip
~x
gleich ist-1-x
. Dies verwendet die gleiche Anzahl von Zeichen, kann jedoch indirekt Leerzeichen oder Parens aus Gründen der Operatorpriorität entfernen.Vergleichen Sie:
Die Betreiber
~
und einstelligen-
sind höhere Priorität als*
,/
,%
, im Gegensatz zu binären+
.quelle
-~-x
speichert ein Byte vs.(1-x)
.a+b+1
die prägnanter als geschrieben werden kanna-~b
.n-i-1
ist einfachn+~i
.Eine gute Möglichkeit, eine iterable in eine Liste in Python 3 zu konvertieren :
Stellen Sie sich vor, Sie haben einige iterable, wie
Aber du brauchst eine Liste:
Es ist sehr nützlich, aus einer Zeichenfolge eine Liste von Zeichen zu erstellen
quelle
*s,='abcde'
und danns
stürzt meinen interaktiven python3 mit einem segfault :([*'abcde']
.Stattdessen
range(x)
können Sie den*
Operator für eine Liste von allem verwenden, wenn Sie den Wert von nicht wirklich verwenden müsseni
:im Gegensatz zu
Wenn Sie dies mehr als zweimal ausführen müssen, können Sie einer Variablen eine beliebige Iterationsvariable zuweisen und diese Variable mit dem gewünschten Bereich multiplizieren:
Hinweis : Dies ist oft länger als
exec"pass;"*8
, daher sollte dieser Trick nur verwendet werden, wenn dies keine Option ist.quelle
[1]*8
kürzer als sindrange(8)
, können Sie auch Platz sparen, weil diesfor i in[...
legal ist, während diesfor i in range...
nicht der Fall ist."exec"pass;"*8
ist deutlich kürzer.r=1
,r*8
ist 8 und Sie können eine Zahl nicht durchlaufen. Ich denke, Sie meintenr=[1]
Sie können das gute alte fremde Smiley-Gesicht verwenden, um Sequenzen umzukehren:
quelle
Erweitertes iterierbares Entpacken ("Markierte Zuweisung", nur Python 3)
Dies lässt sich am besten anhand eines Beispiels erklären:
Wir haben bereits eine Verwendung dafür gesehen - eine iterable in eine Liste in Python 3 verwandeln :
Hier sind noch ein paar Anwendungen.
Das letzte Element aus einer Liste holen
In einigen Situationen kann dies auch verwendet werden, um das erste Element zum Speichern von Parens abzurufen:
Zuweisen einer leeren Liste und anderer Variablen
Erstes oder letztes Element einer nicht leeren Liste entfernen
Diese sind kürzer als die Alternativen
L=L[1:]
undL.pop()
. Das Ergebnis kann auch in einer anderen Liste gespeichert werden.Trinkgelder mit freundlicher Genehmigung von @grc
quelle
a=1;L=[]
so oft geschrieben. Es ist erstaunlich, dass Sie Zeichen für etwas so Unkompliziertes wie dieses speichern können.a,*L=1,
), aber es speichert immer noch eina,*_,b=L
setze Literale in Python2.7
Sie können Sets wie dieses schreiben
S={1,2,3}
Dies bedeutet auch Sie für die Mitgliedschaft überprüfen können mit{e}&S
statte in S
dem speichert ein Zeichen.quelle
if
s, da es keine Leerzeichen gibt (if{e}&S:
)not in
durch{e}-S
diesen Trick ersetzen könnenFür eine Ewigkeit störte es mich, dass ich mir keinen kurzen Weg vorstellen konnte, um das gesamte Alphabet zu bekommen. Wenn Sie
range
genug verwenden, dasR=range
es wert ist, in Ihrem Programm enthalten zu sein, dannist kürzer als die naive
, aber sonst ist es länger von einem einzelnen Zeichen. Es verfolgte mich, dass der Kluge, der etwas Wissen über die ASCII-Werte benötigte, ausführlicher war, als nur alle Buchstaben zu tippen.
Bis ich diese Antwort für das Alphabet meiner Tochter sah . Ich kann den Bearbeitungsverlauf nicht gut genug verfolgen, um herauszufinden, ob dieses Genie das Werk des OP war oder ob es ein Vorschlag eines Kommentators war, aber dies ist (glaube ich) der kürzeste Weg, um einen iterablen der 26 Buchstaben zu erstellen im römischen Alphabet.
Wenn die Groß- / Kleinschreibung keine Rolle spielt, können Sie ein anderes Zeichen mit Großbuchstaben entfernen:
Ich benutze
map
viel zu viel, ich weiß nicht, wie mir das noch nie in den Sinn gekommen ist.quelle
string.lowercase
- dafür ist es da.ord('z')
)? Abgesehen davon, dass es die gleiche Länge hat ... Wenn Sie alphanumerischestr.isalpha
Zeichen benötigen, ersetzen Sie in der Version von @ quintopia durchstr.isalnum
. (Wenn Sie jedoch nur einen Fall benötigen, ist die gesamte Zeichenfolge mit 36 Zeichen nicht länger alsfilter(str.isalnum,map(chr,range(90)))
.)R
, ist meine Version kürzer als Ihre ursprüngliche:'%c'*26%tuple(R(97,123))
(nur 24 Zeichen) Wenn Sie buchstabierenrange
, ist sie genauso lang wie die alphabetische GroßbuchstabenversionObwohl Python keine switch-Anweisungen hat, können Sie sie mit Wörterbüchern emulieren. Zum Beispiel, wenn Sie einen Schalter wie diesen wollten:
Sie könnten
if
Anweisungen verwenden, oder Sie könnten dies verwenden:oder dieses:
Das ist besser, wenn alle Codepfade Funktionen mit denselben Parametern sind.
So unterstützen Sie einen Standardwert:
(oder dieses:)
Ein weiterer Vorteil ist, dass Sie Redundanzen einfach nach dem Ende des Wörterbuchs hinzufügen können:
Und wenn Sie nur einen Schalter verwenden wollten, um einen Wert zurückzugeben:
Sie könnten dies einfach tun:
quelle
dict(s1=v1,s2=v2,...,sn=vn)
anstelle von{'s1':v1,'s2':v2,...,'sn':vn}
2 * n-4 Bytes und ist besser, wenn n> = 3Wenn Sie zwei boolesche Werte haben
a
undb
herausfinden möchten, ob beidea
undb
wahr sind, verwenden Sie*
anstelle vonand
:vs
Wenn einer der Werte falsch ist, wird er wie
0
in dieser Anweisung ausgewertet , und ein ganzzahliger Wert ist nur dann wahr, wenn er ungleich Null ist.quelle
&
:a=b=False
,a&b
+
für,or
wenn Sie garantieren könnena != -b
|
funktioniert in allen Situationen.*
Anstelle vonand
/ werden&&
einige Bytes in vielen Sprachen gespeichert.Exploit Python 2-Zeichenfolgendarstellungen
Mit Python 2 können Sie ein Objekt
x
zu`x`
einem Preis von nur 2 Zeichen in seine Zeichenfolgendarstellung konvertieren . Verwenden Sie diese Option für Aufgaben, die für die Zeichenfolge des Objekts einfacher sind als für das Objekt selbst.Verbinde Charaktere
Ausgehend von einer Liste von Zeichen
l=['a','b','c']
kann man''.join(l)
as erzeugen`l`[2::5]
, wodurch ein Byte eingespart wird.Der Grund hierfür ist , dass
`l`
ist"['a', 'b', 'c']"
(mit Leerzeichen), so dass man die Buchstaben mit einer Liste slice extrahieren kann, ausgehend , dass der zweite Null-indizierte Charaktera
, und von dort jedes fünften Zeichen nehmen. Dies funktioniert nicht, um Zeichenfolgen mit mehreren Zeichen oder Escape-Zeichen zu verbinden, die wie dargestellt werden'\n'
.Zahlen verketten
In ähnlicher Weise eine nicht-leere Liste der Stellen gegeben wie
l=[0,3,5]
, man sich in eine String verketten kann'035'
wie`l`[1::3]
.Das spart so etwas wie
map(str,l)
. Beachten Sie, dass es sich um einzelne Ziffern handeln muss und dass keine Gleitkommazahlen wie1.0
gemischt verwendet werden dürfen]
.Auf Negative prüfen
Nun zu einer Aufgabe ohne Zeichenfolge. Angenommen, Sie haben eine Liste
l
von reellen Zahlen und möchten testen, ob sie negative Zahlen enthalten, wodurch ein Boolescher Wert erzeugt wird.Du kannst tun
Das prüft auf ein negatives Vorzeichen in der Zeichenfolge rep. Dies ist kürzer als eines von beiden
Zum zweiten
min(l)<0
würde das auf der leeren Liste scheitern, so dass man sich absichern muss.quelle
str(l)[2::5]
beträgt 12 Byte gegenüber 19 für''.join(map(str,l))
. Eine tatsächliche Situation, in der dies auftrat (wol
es eine Generatoranweisung gab, keine Liste), hat mir nur ein Byte gespart ... das ist es immer noch wert!Eine einzeilige Funktion kann mit Lambda ausgeführt werden:
kann konvertiert werden zu (notiere fehlendes Leerzeichen
3and
und10or
)quelle
c=lambda a:a+[-5,10][a<3]
. Der und / oder Trick ist nützlicher, wenn Sie vom Kurzschlussverhalten abhängig sindelse:
Kann in Ihrer Funktion gelöscht werden, wennreturn
die Ausführung der Funktion gestoppt wird, sodass alles, was folgt, nur ausgeführt wird, wenn dieif
Bedingung fehlgeschlagen ist, auch bekannt als, wenn dieelse
Bedingung wahr ist. Somitelse
kann gefahrlos aufgehoben werden. (Ausführlich erklärt für die Neophyten da draußen)c=lambda a:a-5+15*(a<3)
Schleifen von bis zu 4 Elementen sind möglicherweise besser, um ein Tupel zu liefern, als range zu verwenden
vs
quelle
Decke und Boden
Wenn Sie jemals das aufgerundete Ergebnis für eine Division erhalten möchten, wie Sie es
//
für Floor tun würden , können Sie esmath.ceil(3/2)
für 15 oder das viel kürzere-(-3//2)
für 8 Bytes verwenden.quelle
n//1+1
anstatt mit ceil, aber es bedeutet ceil (n) = n + 1, aber es sollte für alle nicht ganzzahligen Werteround(x)
ist(x+.5)//1
, +1 Byte, letzteres beginnt jedoch mit a(
, und wennx
es sich um eine Summe handelt, die aus einer Konstanten besteht, kann dies nützlich sein.Verwenden Sie
+=
anstelle vonappend
undextend
kann gekürzt werden auf:
B,
Hier wird ein Tupel mit einem Element erstellt, mit dem Sie die ErweiterungA
wie[B]
in ausführen könnenA+=[B]
.kann gekürzt werden auf:
quelle
return 0
oderreturn 1
entsprichtreturn False
oderreturn True
.-x
eher alsx*-1
.--8.32
eher als-8.32*-1
. Oder einfach8.32
...A+=B
B
isttuple
.Auswahl einer von zwei Zahlen basierend auf einer Bedingung
Es ist bereits bekannt , die Listenauswahl
[x,y][b]
mit einem Booleschen Wertb
für den ternären Ausdruck zu verwendeny if b else x
. Die Variablenx
,y
undb
können auch Ausdrücke, obwohl beachten Sie, dass beidex
undy
werden auch ausgewertet , wenn sie nicht ausgewählt.Hier sind einige mögliche Optimierungen, wenn
x
undy
sind Zahlen.[0,y][b] -> y*b
[1,y][b] -> y**b
[x,1][b] -> b or x
[x,x+1][b] -> x+b
[x,x-1][b] -> x-b
[1,-1][b] -> 1|-b
[x,~x][b] -> x^-b
[x,y][b] -> x+z*b
(odery-z*b
), wobei z = yx.Sie können auch wechseln
x
undy
wenn Sie umschreiben kannb
seine Negation anstatt zu sein.quelle
Verwenden Sie ~, um am Ende einer Liste zu indizieren
Wenn
L
es sich um eine Liste handelt, verwenden SieL[~i]
diese Option, um dasi
'te Element von hinten abzurufen.Dies ist das
i
'te Element der Umkehrung vonL
. Das Bitkomplement ist~i
gleich-i-1
und behebt so den Fehler von Off-by-OneL[-i]
.quelle
PEP448 - Zusätzliche Verallgemeinerungen beim Auspacken
Mit der Veröffentlichung von Python 3.5 wurde die Manipulation von Listen, Tupeln, Sätzen und Dikten noch golfer.
Aus einer Iteration wird eine Menge / Liste
Vergleichen Sie die Paare:
Viel kürzer! Beachten Sie jedoch, dass das normale, erweiterte, wiederholbare Entpacken kürzer ist , wenn Sie nur etwas in eine Liste konvertieren und einer Variablen zuweisen möchten :
Eine ähnliche Syntax funktioniert für Tupel:
das ist wie ausgedehntes iterables Auspacken, aber mit dem Sternchen und dem Komma auf der anderen Seite.
Listen / Tupel verbinden
Das Entpacken ist etwas kürzer als das Verketten, wenn Sie eine Liste / ein Tupel an beide Seiten anhängen müssen:
Inhalt mehrerer Listen drucken
Dies ist nicht beschränkt auf
print
, aber es ist definitiv, wo der größte Teil der Laufleistung herkommt. PEP448 ermöglicht jetzt das mehrfache Auspacken wie folgt:Aktualisieren mehrerer Wörterbuchelemente
Dies wird wahrscheinlich nicht sehr oft vorkommen, aber die Syntax kann verwendet werden, um beim Aktualisieren von Wörterbüchern zu sparen, wenn Sie mindestens drei Elemente aktualisieren:
Dies negiert grundsätzlich jegliche Notwendigkeit
dict.update
.quelle
Wechseln Sie
import *
zuimport*
Wenn Sie nicht gehört haben,
import*
speichert Zeichen!ist nur 1 Zeichen länger als
import math as m
und Sie können alle Instanzen von entfernenm.
Schon der einmalige Gebrauch spart!
quelle
wenn der Wert von i nutzlos ist:
oder
quelle
for i in[0]*x:s+=input()
einen anderen Platz machen. Sie können auch das Leerzeichen zwischen dem exec und dem ersten Anführungszeichen entfernen, um zu erhaltenexec's+=input();'*x
for i in[0]*x:s+=input()