Wie kann ich in Python Alias-Mitgliederfunktionen verwenden?

23

In Python kann man durch Aliasing-Funktionen, die wiederholt verwendet werden, Bytes sparen. Beispielsweise:

r=range
a=r(100)
b=r(200)
c=r(300)

Wenn die Funktionen zusammen Elementfunktionen sind, kann ich sie jedoch nicht so aliasisieren, dass eine Verkettung möglich ist. Beispielsweise:

s='Hello'

// Plain code
s=s.replace('H','J').replace('e','i').replace('l','m').replace('o','y')

// What I am trying to do
q=replace
s=s.q('H','J').q('e','i').q('l','m').q('o','y')

Offensichtlich ist das, was ich versuche, nicht gültig. Und das ist auch nicht:

q=s.replace
s=q('H','J') // Replaces the 'H' in 'Hello'
s=q('e','i') // Replaces the 'e' in 'Hello'... and the J is gone.
s=q('l','m')
s=q('o','y')

Gibt es eine andere Möglichkeit, Mitgliedsfunktionen und verkettete Funktionen zu aliasen, um Zeichen zu speichern?

Regenblitz
quelle
Definieren Sie Ihre eigene Klasse, wobei die Methode qbedeutet, was replacein der Klasse Ihre Verwendung bedeutet.
Ypnypn
3
Ich bin froh, dass dies nicht herabgestuft wurde :)
TheDoctor
2
Ich habe vorerst alle Antworten nicht beantwortet, aber wir haben noch keinen Konsens gefunden, der es erforderlich macht, diese und ähnliche Fragen nicht zu beantworten. Siehe auch: meta.codegolf.stackexchange.com/q/1555/3808
Türklinke
3
Jetzt, da die oben genannte Metadiskussion nur noch halb amtlich ist (oder zumindest die meisten von uns zustimmen), habe ich das Wiki für diesen Beitrag entfernt.
Türklinke
1
Ihre letzte Version funktioniert nicht. qist an die Ersetzungsmethode dieser bestimmten strInstanz gebunden . "Hello".replace(*"HJ")
Denken

Antworten:

28

Kein Problem! Sie können eine Methode aliasen, aber Sie müssen wissen, wie man sie verwendet:

>>> r=str.replace
>>> a='hello'
>>> r(r(r(r(a,'h','j'),'e','i'),'l','m'),'o','y')
'jimmy'

Der Schlüssel ist, dass Sie selfexplizit übergeben müssen, da der Alias ​​eine Art Funktion ist, die ein zusätzliches Argument benötigt, das Folgendes beinhaltet self:

>>> type(r)
<type 'method_descriptor'>
MtnViewMark
quelle
3
Wie habe ich das vorher nicht gesehen?
Rainbolt
6

Definieren Sie Ihre eigene Klasse mit einem kürzeren Methodennamen.

Wenn Sie beispielsweise replace()die zur StringKlasse gehörende Methode verwenden , können Sie Ihrer eigenen Klasse Seine Methode mit qdem gleichen Namen zuweisen.

Hier ist eine Implementierung:

class m(str):
 def q(a,b,c):return m(a.replace(b,c))

Hier ist eine viel bessere Implementierung:

class m(str):q=lambda a,b,c:m(a.replace(b,c))

Benutze es so:

s="Hello"
s=m(s).q('H','J').q('e','i').q('l','m').q('o','y')
Ypnypn
quelle
5

Dies ist sowieso ein paar Zeichen kürzer

j=iter('HJeilmoy')
for i in j:s=s.replace(i,next(j))

noch kürzer für eine kleine Anzahl von Ersatzteilen ist

for i in['HJ','ei','lm','oy']:s=s.replace(*i)

Dies deckt natürlich nur einen bestimmten Fall ab. Beim Codegolf geht es jedoch nur darum, die Sonderfälle zu finden, die Ihnen Byte sparen können.

Es ist möglich, eine Wrapper-Funktion zu schreiben, die den allgemeinen Fall behandelt, aber der Code ist zu groß, um einen Platz in den meisten Code-Golf-Herausforderungen zu haben.

Sie müssen stattdessen denken: "Ich kann diese Transformation effizient (strichweise) mit str.replace durchführen. Kann ich die interne Darstellung meiner Lösung verschieben, um dies zu nutzen? (Ohne so viele Striche zu verschwenden, um den Vorteil zu negieren)."

Knabberzeug
quelle
Ich mag diese Antwort, weil sie gute Gewohnheiten beim Golfen beschreibt und definitiv das angegebene Beispiel löst. Ich habe eine andere Antwort akzeptiert, da sie für den allgemeineren Fall gilt.
Rainbolt
4

Sie können die reduceFunktion verwenden.

reduce(lambda s,(a,b):s.replace(a,b),[('H','J'),('e','i'),('l','m'),('o','y')],'Hello')
Howard
quelle
Wenn Ihre Antwort von dieser Antwort abweicht (was die verwendete Technik anbelangt, muss sie nicht exakt in derselben Form geschrieben sein)?
Rainbolt
1
@ Rusher Es ist anders. Beispielsweise ist die Anzahl der Aufrufe in der verknüpften Antwort fest codiert, während sie hier nur durch die Länge des zweiten Arguments (das ein beliebiger Iterator sein kann) gegeben ist.
Howard
1

Wenn Sie viele Ersetzungen durchführen, können Sie dies tun:

s=''.join({'H':'J','e':'i','l':'m','o':'y'}[a] for a in list(s))
Der Doktor
quelle
Ich hatte auf eine Antwort gehofft, die nicht spezifisch zu ersetzen war. Ich habe das nur als Beispiel genommen.
Rainbolt
Dies kann jeweils nur 1 Zeichen ersetzen, es können jedoch mehrere Zeichen ersetzt werden. Und dies ist nicht vollständig Golf (entfernen Sie das Leerzeichen danach [a])
Justin
2
Muss das nicht [a]durch ersetzt werden .get(a,a)(sonst bekommen wir eine Schlüsselfehlersache)? Und warum list(s)statt s?
Justin
1

Wie wäre es mit der Definition einer Lambda-Funktion?

r=lambda s,a,b:s.replace(a,b)

s=r(r(r(r(s,'H','J'),'e','i'),'l','m'),'o','y')
Justin
quelle
1
Keine Notwendigkeit: str.replace/ ist / das Lambda! Siehe meine Antwort.
MtnViewMark
1

Wenn Ihre Ersetzungen nicht angekettet werden müssen, können Sie "str.translate" verwenden. Die Zahlen sind die ASCII-Ordnungszahlen. Für diese Verwendung ist Python 3 erforderlich:

print("Hello".translate({72:74,101:105,108:109,111:121}))

Probieren Sie es online aus

mbomb007
quelle