Come posso alias funzioni membro in Python?


23

In Python, è possibile salvare byte aliasando le funzioni utilizzate più volte. Per esempio:

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

Tuttavia, quando le funzioni sono funzioni membro insieme, non so come alias in un modo che consenta il concatenamento. Per esempio:

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

Ovviamente, ciò che sto cercando di fare non è valido. E nemmeno questo:

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

C'è un altro modo per le funzioni membro alias e le funzioni concatenate che salva i personaggi?


Definisci la tua classe, con il suo metodo che qsignifica cosa replacesignifica nella classe che stai usando.
Ypnypn,

3
Sono contento che questo non sia stato sottovalutato :)
TheDoctor

2
Per il momento ho scartato tutte le risposte, ma non abbiamo raggiunto un consenso abbastanza forte da chiedere di scartare questa e altre domande simili. Vedi anche: meta.codegolf.stackexchange.com/q/1555/3808
Maniglia della porta

3
Ora che la suddetta meta discussione è semi-ufficiale (o almeno la maggior parte di noi è d'accordo), sono andato avanti e ho rimosso il wiki in questo post.
Maniglia della porta

1
La tua ultima versione non funziona. qè vincolato al metodo di sostituzione di quella specifica stristanza. Inoltre, ricorda che puoi fare sostituzioni di caratteri singoli con"Hello".replace(*"HJ")
gnibbler

Risposte:


28

Nessun problema! Puoi alias un metodo, ma devi sapere come usarlo:

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

La chiave è che devi passare selfesplicitamente, perché l'alias è un tipo di funzione che accetta un argomento aggiuntivo che accetta self:

>>> type(r)
<type 'method_descriptor'>

3
Come non l'ho visto prima?
Rainbolt

6

Definisci la tua classe, con un nome metodo più breve.

Ad esempio, se stai usando il metodo replace()appartenente alla Stringclasse, potresti fare in modo che la tua classe Sabbia un metodo chiamato qche fa la stessa cosa.

Ecco una implementazione:

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

Ecco un'implementazione molto migliore:

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

Usalo così:

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

5

Questo è comunque alcuni caratteri più corti

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

è ancora più breve per un numero limitato di sostituzioni

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

ovviamente questo copre solo un caso particolare. Tuttavia, il golf del codice consiste nel trovare quei casi speciali che possono farti risparmiare byte.

È possibile scrivere una funzione wrapper che gestisca il caso generale, ma il codice sarà troppo grande per avere un posto nella maggior parte delle sfide del golf del codice.

Devi invece pensare "Posso fare questa trasformazione in modo efficiente (a tratti) con str.replace. Posso spostare la rappresentazione interna della mia soluzione per trarne vantaggio? (Senza sprecare così tanti colpi per negare il vantaggio)"


Mi piace questa risposta perché descrive le buone abitudini durante il golf e risolve definitivamente l'esempio specifico presentato. Ho accettato un'altra risposta perché è applicabile al caso più generale.
Rainbolt

4

È possibile utilizzare la reducefunzione.

reduce(lambda s,(a,b):s.replace(a,b),[('H','J'),('e','i'),('l','m'),('o','y')],'Hello')

Se la vostra risposta diversa da questa risposta (per quanto riguarda la tecnica usata, non necessariamente scritto nella esattamente stessa forma)?
Rainbolt,

1
@Rusher È diverso. Ad esempio, il numero di invocazioni è codificato nella risposta collegata mentre qui è dato solo dalla lunghezza del secondo argomento (che può essere qualsiasi iteratore).
Howard,

1

Se stai facendo molte sostituzioni, puoi farlo:

s=''.join({'H':'J','e':'i','l':'m','o':'y'}[a] for a in list(s))

Speravo in una risposta che non fosse specifica da sostituire. L'ho appena usato come esempio.
Rainbolt

Questo può sostituire solo 1 carattere alla volta, ma può inserire sostituzioni di più caratteri. E questo non è completamente golfato (rimuovi lo spazio dopo [a])
Giustino

2
Non [a]è necessario sostituirlo con .get(a,a)(altrimenti, otteniamo qualcosa di errore chiave)? E perché list(s)invece di s?
Justin

1

Che ne dici di definire una funzione lambda?

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

s=r(r(r(r(s,'H','J'),'e','i'),'l','m'),'o','y')

1
Non c'è bisogno: str.replace/ è / che lambda! Vedi la mia risposta
MtnViewMark

1

Se i tuoi sostituti non hanno bisogno di essere concatenati, puoi usare `str.translate '. I numeri sono gli ordinali ASCII. Usarlo in questo modo richiede Python 3:

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

Provalo online

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.