Como alias as funções de membro no Python?


23

No Python, é possível salvar bytes alterando as funções que são usadas repetidamente. Por exemplo:

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

No entanto, quando as funções são funções membro juntas, não sei como aliasá-las de uma maneira que permita o encadeamento. Por exemplo:

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

Obviamente, o que estou tentando fazer não é válido. E também não é isso:

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

Existe outra maneira de alias funções membro e funções encadeadas que salvam caracteres?


Defina sua própria classe, com seu método qsignificando o que replacesignifica na classe que você está usando.
Ypnypn

3
Estou contente isso não foi downvoted :)
TheDoctor

2
Eu desativei todas as respostas por enquanto, mas ainda não chegamos a um consenso forte o suficiente para pedir que essas e outras perguntas semelhantes sejam desatendidas. Veja também: meta.codegolf.stackexchange.com/q/1555/3808
Maçaneta da

3
Agora que a meta discussão acima é semioficial (ou pelo menos a maioria de nós concorda), fui em frente e removi o wiki deste post.
Maçaneta

1
Sua última versão não funciona. qestá vinculado ao método de substituição dessa strinstância específica . Além disso, lembre-se que você pode fazer substituições de char único com"Hello".replace(*"HJ")
gnibbler

Respostas:


28

Não há problema! Você pode usar um método alternativo, mas precisa saber como usá-lo:

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

A chave é que você precisa passar selfexplicitamente, porque o alias é um tipo de função que usa um argumento extra que usa self:

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

3
Como eu não vi isso antes?
Rainbolt 14/05

6

Defina sua própria classe, com um nome de método mais curto.

Por exemplo, se você estiver usando o método replace()pertencente à Stringclasse, poderá fazer com que sua própria classe Stenha um método chamado qque faça a mesma coisa.

Aqui está uma implementação:

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

Aqui está uma implementação muito melhor:

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

Use-o assim:

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

5

Este é alguns caracteres mais curtos de qualquer maneira

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

ainda mais curto para um pequeno número de substituições é

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

é claro que isso apenas cobre um caso particular. No entanto, o código golf consiste em encontrar os casos especiais que podem economizar bytes.

É possível escrever uma função de wrapper que lide com o caso geral, mas o código será muito grande para ter um lugar na maioria dos desafios de golfe com código.

Em vez disso, você precisa pensar "Eu posso fazer essa transformação de maneira eficiente (strokewise) com str.replace. Posso mudar a representação interna da minha solução para tirar proveito disso? (Sem desperdiçar tantos traços para negar a vantagem)"


Eu gosto desta resposta porque descreve bons hábitos ao jogar golfe e definitivamente resolve o exemplo específico apresentado. Aceitei outra resposta porque é aplicável ao caso mais geral.
Rainbolt 14/05

4

Você pode usar a reducefunção

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

Se sua resposta diferente de esta resposta (tanto quanto técnica usada, não necessariamente escrito na exata mesma forma)?
Rainbolt

1
@Rusher É diferente. Por exemplo, o número de invocações é codificado na resposta vinculada, enquanto aqui é fornecido apenas pelo comprimento do segundo argumento (que pode ser qualquer iterador).
1011 Howard

1

Se você estiver fazendo muitas substituições, poderá fazer o seguinte:

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

Eu esperava uma resposta que não fosse específica para substituir. Eu apenas usei isso como exemplo.
Rainbolt

Isso pode substituir apenas 1 caracter por vez, mas pode inserir substituições de vários caracteres. E isso não está totalmente golfed (remover o espaço depois [a])
Justin

2
Ele não [a]precisa ser substituído por .get(a,a)(caso contrário, obtemos alguma coisa de Erro de chave)? E por que ter em list(s)vez de s?
Justin

1

Que tal definir uma função 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
Não há necessidade: str.replace/ é / que lambda! Veja minha resposta.
MtnViewMark

1

Se suas substituições não precisarem ser encadeadas, você pode usar o `str.translate '. Os números são os ordinais ASCII. Usá-lo dessa maneira requer Python 3:

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

Experimente online

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.