Dies ist eine Tippfrage zum Golfen in Python.
Beim Python-Golfen ist es üblich, dass eine Vorlage eine als Lambda definierte Funktion ist. Beispielsweise,
f=lambda x:0**x or x*f(x-1)
berechnet die Fakultät von x.
Das Lambda-Format hat zwei große Vorteile :
- Die Kesselplatte von
f=lambda x:...
oderlambda x:...
ist kürzer als die vondef f(x):...return...
oderx=input()...print...
- Ein rekursiver Aufruf kann verwendet werden, um eine Schleife mit geringem Byte-Overhead auszuführen.
Lambdas haben jedoch den großen Nachteil, dass sie nur einen einzigen Ausdruck zulassen, keine Aussagen. Insbesondere bedeutet dies keine Zuordnungen wie c=chr(x+65)
. Dies ist problematisch, wenn ein langer Ausdruck vorhanden ist, auf dessen Wert zweimal (oder öfter) verwiesen werden muss.
Zuweisungen wie E=enumerate
sind außerhalb der Funktion oder als optionales Argument möglich, jedoch nur, wenn sie nicht von den Funktionseingaben abhängen. Optionale Argumente wie f=lambda n,k=min(n,0):...
fail, da die Eingabe n
nicht definiert wurde, wenn sie k
zum Definitionszeitpunkt ausgewertet wird.
Das Ergebnis ist, dass Sie manchmal einen langen Ausdruck in einem Lambda wiederholen, weil die Alternative ein langwieriges Nicht-Lambda ist.
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]
Die Gewinnschwelle beträgt ungefähr 11 Zeichen ( Details ), nach denen Sie zu einem def
oder wechseln program
. Vergleichen Sie dies mit dem üblichen Break-Even der Länge 5 für einen wiederholten Ausdruck:
range(a)+range(b)
r=range;r(a)+r(b)
print s[1:],s[1:]*2
r=s[1:];print r,r*2
Andere Sprachen haben Workarounds, zum Beispiel Octave . Es gibt bekannte Tricks für Python, aber sie sind langwierig, klobig und / oder nur eingeschränkt verwendbar. Eine kurze, universelle Methode zur Simulation der Zuordnung in einem Lambda würde das Python-Golfen revolutionieren.
Wie kann ein Python-Golfer diese Einschränkung überwinden oder umgehen? Welche potenziellen Ideen sollten sie in Betracht ziehen, wenn sich ein langer Ausdruck in einem Lambda zweimal wiederholt?
Mein Ziel mit dieser Frage ist es, tief in dieses Problem einzutauchen und:
- Katalogisieren und analysieren Sie Golf-Workarounds, um die Zuordnung innerhalb eines Lambdas zu fälschen
- Entdecken Sie neue Leads für bessere Methoden
Jede Antwort sollte eine Problemumgehung oder einen möglichen Hinweis enthalten.
lambda s:(s+s[::-1]).lower()
. Dies beantwortet natürlich nicht die eigentliche Frage.strip
.Antworten:
eval
Dies ist an sich nicht so toll, aber wenn Ihre Lösung bereits
eval
auf irgendeine Weise oder in irgendeiner Form verwendet wird, können Sie normalerweise diese Technik verwenden.quelle
Zuweisungsausdrücke in Python 3.8
In Python 3.8 ( TIO ) werden Zuweisungsausdrücke eingeführt , mit denen
:=
eine Variable inline als Teil des Ausdrucks zugewiesen wird.Dies kann innerhalb von verwendet werden
lambda
, wo Zuweisungen normalerweise nicht zulässig sind. Vergleichen Sie:Weitere Informationen finden Sie in diesem Tipp .
quelle
Innere Lambdas
Mit diesen können Sie mehrere Variablen gleichzeitig definieren.
gegen
ist viel länger, aber wenn Sie mehrere oder längere Variablen haben, die oft wiederholt werden:
gegen
Zeichenanzahl
Anfänglich:
(lambda:)()
(11 Bytes)Erste Variable:
[space]a
(2 Bytes)Nachfolgende Variablen:
,b,
(3 Bytes)Verwendung:
a
(1 Byte).(Spart auch an Klammern)
Dies dauert also
3n + 10
Bytes, wobein
die Anzahl der Variablen ist. Dies ist ein hoher Anfangsaufwand, der sich aber am Ende auszahlen kann. Es gibt sogar seinen inneren Wert zurück, so dass Sie mehrere verschachteln können (dies wird sich jedoch schnell nicht mehr lohnen.)Dies ist wirklich nur für lange Zwischenberechnungen in verschachtelten Listenverstehen nützlich, da
def f():a=...;b=...;return
es normalerweise kürzer sein wird.Bei einem Wert von 1 wird dadurch Folgendes gespeichert: Dies
uses * length - length - uses - 13
ist nur nützlich, wenn dieser Ausdruck positiv ist.Für
n
verschiedene Ausdrücke, dieu
insgesamt mal verwendet werden und deren kombinierte Länge beträgtl
, wird Folgendes gespart:l - (3 * n) - u - 10 ( + brackets removed )
quelle
Verwenden Sie eine Liste
Deklarieren Sie eine Liste als Parameter und verwenden Sie
.append() or
, um den Wert zu speichern:lambda s:s.lower()+s.lower()[::-1]
wird zu
lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]
Zeichenanzahl:
,l=[]
5 Zeichenl.append()or
13 Zeichenl[-1]
5 Zeichen für jede VerwendungDie Gewinnzone erreichen
Die Anzahl der hinzugefügten Zeichen beträgt:
uses*(5-length) + 18 + length
Im vorherigen Beispiel ist die Anweisung
s.lower()
9 Zeichen lang und wird zweimal verwendet, wobei diese Technik angewendet wird und 19 Zeichen hinzugefügt werden. Wenn es 7 Mal verwendet würde, würde es eine Zeichenreduktion von 1 geben.Die Menge an minimalen Einsätzen, die diese Technik wert sein kann, ist
min_uses = (18+length)/(length-5)
Upsides
list
Objekt so[0]
,.pop()
,[x:y]
und andere Listenfunktionen können für Tricks verwendet werden. sehr situativNachteile
5
Benutze ein Wörterbuch
thanks @Zgarb
Gleiche Idee wie oben Deklarieren Sie ein Wörterbuch als Parameter und verwenden Sie es
.setdefault()
, um den Wert zu speichern (und zurückzugeben):lambda s:s.lower()+s.lower()[::-1]
wird zu
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
Beachten Sie, dass im Gegensatz zum
list
Gegenstücksetdefault
der zugewiesene Wert zurückgegeben wird.Zeichenanzahl:
,d={}
5 Zeichend.setdefault(k,)
16 Zeichend[k]
4 Zeichen für jede VerwendungDie Gewinnzone erreichen
Die Anzahl der hinzugefügten Zeichen beträgt:
(uses-1)*(4-length) + 21
Im vorherigen Beispiel ist die Anweisung
s.lower()
9 Zeichen lang und wird zweimal verwendet, wobei diese Technik angewendet wird und 16 Zeichen hinzugefügt werden. Wenn es 7 Mal verwendet würde, würde es eine Zeichenreduktion von 1 geben.Die Menge an minimalen Einsätzen, die diese Technik wert sein kann, ist
min_uses = 1-21/(4-length)
Vor- / Nachteile
4
Andere Überlegungen
lambda
kann die wahrscheinlich fallengelassen und die Funktion mitdef
/input
für ein kürzeres Programm umgeschrieben werden.quelle
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
Es ist auch wiederverwendbar.list.extend
Sie mehrere Elemente gleichzeitig hinzufügen. Dies ist kürzer als dielist.append
mehrfache Verwendung .Verwenden Sie diese Option, um Variablen festzulegen und die Daten nach der Operation wie folgt zurückzugeben:
quelle
Listenverständnisse
Dies ist eher ein letzter Ausweg, da es so unrühmlich ist, aber Sie können
[<expression> for <variable> in <value>]
eine Variable in einem Lambda pseudo-setzen. Grundsätzlich ist das einzig Gute an dieser Methode, dass der innere Ausdruck lesbar bleibt, was Sie beim Golfen offensichtlich am wenigsten interessiert.
quelle