Jak mam alias funkcje członka w Pythonie?

23

W Pythonie można zapisywać bajty, używając wielokrotnie używanych funkcji aliasingu. Na przykład:

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

Jednak gdy funkcje są funkcjami składowymi razem, nie wiem, jak je aliasować w sposób umożliwiający tworzenie łańcuchów. Na przykład:

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')

Oczywiście to, co próbuję zrobić, jest nieprawidłowe. I to też nie jest:

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')

Czy istnieje inny sposób na alias funkcji składowych i funkcji łańcuchowych, który zapisuje znaki?

Rainbolt
źródło
Zdefiniuj własną klasę za pomocą jej metody, która qoznacza, co replacew klasie używasz.
Ypnypn
3
Cieszę się, że nie zostało to wzięte pod uwagę :)
TheDoctor
2
Na razie nie znałem odpowiedzi na wszystkie pytania, ale nie osiągnęliśmy wystarczająco silnego konsensusu, aby wezwać do odpowiedzi na te i podobne pytania. Zobacz także: meta.codegolf.stackexchange.com/q/1555/3808
Gałka
3
Teraz, gdy wspomniana wyżej meta dyskusja jest półoficjalna (lub przynajmniej większość z nas się zgodzi), poszedłem dalej i usunąłem wiki w tym poście.
Klamka
1
Twoja ostatnia wersja nie działa. qjest związany z metodą zamiany tego konkretnego strwystąpienia. Pamiętaj też, że możesz robić zamiany pojedynczych "Hello".replace(*"HJ")
znaków za

Odpowiedzi:

28

Bez problemu! Możesz aliasować metodę, ale musisz wiedzieć, jak jej użyć:

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

Kluczem jest to, że musisz przekazać selfjawnie, ponieważ alias jest rodzajem funkcji, która wymaga dodatkowego argumentu, który przyjmuje self:

>>> type(r)
<type 'method_descriptor'>
MtnViewMark
źródło
3
Jak wcześniej tego nie widziałem?
Rainbolt
6

Zdefiniuj własną klasę za pomocą krótszej nazwy metody.

Na przykład, jeśli używasz metody replace()należącej do Stringklasy, możesz stworzyć własną klasę S, qktóra ma wywoływaną metodę, która robi to samo.

Oto jedna implementacja:

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

Oto znacznie lepsze wdrożenie:

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

Używaj go w ten sposób:

s="Hello"
s=m(s).q('H','J').q('e','i').q('l','m').q('o','y')
Ypnypn
źródło
5

To i tak jest kilka znaków krótszych

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

jest jeszcze krótszy dla niewielkiej liczby zamienników

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

oczywiście dotyczy to tylko jednego konkretnego przypadku. Jednak Code Golf polega na znalezieniu specjalnych przypadków, które mogą zaoszczędzić bajty.

Możliwe jest napisanie funkcji otoki, która obsługuje ogólny przypadek, ale kod będzie zbyt duży, aby mógł znaleźć się w większości wyzwań związanych z golfem.

Zamiast tego musisz pomyśleć: „Mogę przeprowadzić tę transformację efektywnie (strokewise) za pomocą str .replace. Czy mogę zmienić wewnętrzną reprezentację mojego rozwiązania, aby z tego skorzystać?

gnibbler
źródło
Podoba mi się ta odpowiedź, ponieważ opisuje dobre nawyki podczas gry w golfa i zdecydowanie rozwiązuje konkretny przedstawiony przykład. Przyjąłem inną odpowiedź, ponieważ dotyczy ona bardziej ogólnego przypadku.
Rainbolt
4

Możesz użyć tej reducefunkcji.

reduce(lambda s,(a,b):s.replace(a,b),[('H','J'),('e','i'),('l','m'),('o','y')],'Hello')
Howard
źródło
Jeśli Twoja odpowiedź różni się od tej (jeśli chodzi o technikę, niekoniecznie jest napisana dokładnie w tej samej formie)?
Rainbolt
1
@Rusher Jest inaczej. Np. Liczba wywołań jest zakodowana na stałe w połączonej odpowiedzi, podczas gdy tutaj jest podana tylko przez długość drugiego argumentu (którym może być dowolny iterator).
Howard
1

Jeśli wykonujesz wiele wymian, możesz to zrobić:

s=''.join({'H':'J','e':'i','l':'m','o':'y'}[a] for a in list(s))
Doktor
źródło
Miałem nadzieję na odpowiedź, która nie byłaby konkretna do zastąpienia. Po prostu użyłem tego jako przykładu.
Rainbolt
Może to zastąpić tylko 1 znak na raz, ale może wstawić zamienniki wielu znaków. I to nie jest w pełni gra w golfa (usuń przestrzeń później [a])
Justin
2
Czy nie [a]trzeba tego zamieniać .get(a,a)(w przeciwnym razie dostajemy coś z kluczowym błędem)? A dlaczego list(s)zamiast s?
Justin
1

Co powiesz na zdefiniowanie funkcji lambda?

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

s=r(r(r(r(s,'H','J'),'e','i'),'l','m'),'o','y')
Justin
źródło
1
Nie ma potrzeby: str.replace/ is / that lambda! Zobacz moją odpowiedź.
MtnViewMark
1

Jeśli zamienniki nie muszą być powiązane, możesz użyć `str.translate '. Liczby są liczbami porządkowymi ASCII. Używanie go w ten sposób wymaga Python 3:

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

Wypróbuj online

mbomb007
źródło