¿Cómo alias funciones miembro en Python?

23

En Python, uno puede guardar bytes aliasing funciones que se utilizan repetidamente. Por ejemplo:

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

Sin embargo, cuando las funciones son funciones miembro juntas, no sé cómo asignar un alias de una manera que permita el encadenamiento. Por ejemplo:

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, lo que estoy tratando de hacer no es válido. Y tampoco es esto:

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

¿Hay alguna otra forma de alias de funciones miembro y funciones encadenadas que guarde caracteres?

Perno de lluvia
fuente
Defina su propia clase, con su método que qsignifica lo que replacesignifica en la clase que está utilizando.
Ypnypn
3
Me alegro de que esto no haya sido rechazado :)
TheDoctor
2
Por ahora, no he descartado todas las respuestas, pero no hemos alcanzado un consenso lo suficientemente fuerte como para exigir que se descarten esta y otras preguntas similares. Vea también: meta.codegolf.stackexchange.com/q/1555/3808
Doorknob
3
Ahora que la meta discusión antes mencionada es semioficial (o al menos la mayoría de nosotros estamos de acuerdo), seguí adelante y eliminé el wiki en esta publicación.
Pomo de la puerta
1
Tu última versión no funciona. qestá vinculado al método de reemplazo de esa strinstancia específica . Además, recuerde que puede hacer reemplazos de caracteres individuales con"Hello".replace(*"HJ")
gnibbler

Respuestas:

28

¡No hay problema! Puede usar un alias para un método, pero debe saber cómo usarlo:

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

La clave es que debe pasar selfexplícitamente, porque el alias es un tipo de función que toma un argumento adicional que toma self:

>>> type(r)
<type 'method_descriptor'>
MtnViewMark
fuente
3
¿Cómo no vi esto antes?
Rainbolt
6

Defina su propia clase, con un nombre de método más corto.

Por ejemplo, si está utilizando el método que replace()pertenece a la Stringclase, podría hacer que su propia clase Stenga un método llamado qque haga lo mismo.

Aquí hay una implementación:

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

Aquí hay una implementación mucho mejor:

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

Úselo así:

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

Esto es unos caracteres más cortos de todos modos

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

incluso más corto para un pequeño número de reemplazos es

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

Por supuesto, esto solo cubre un caso particular. Sin embargo, el código de golf se trata de encontrar esos casos especiales que pueden ahorrarle bytes.

Es posible escribir una función de contenedor que maneje el caso general, pero el código será demasiado grande para tener un lugar en la mayoría de los desafíos de golf de código.

En cambio, debe pensar "Puedo hacer esta transformación de manera eficiente (trazo) con str.replace. ¿Puedo cambiar la representación interna de mi solución para aprovechar eso? (Sin desperdiciar tantos trazos para negar la ventaja)"

gnibbler
fuente
Me gusta esta respuesta porque describe buenos hábitos al jugar al golf y definitivamente resuelve el ejemplo específico presentado. Acepté otra respuesta porque es aplicable al caso más general.
Rainbolt
4

Puedes usar la reducefunción.

reduce(lambda s,(a,b):s.replace(a,b),[('H','J'),('e','i'),('l','m'),('o','y')],'Hello')
Howard
fuente
Si su respuesta es diferente de esta respuesta (en cuanto a la técnica utilizada, no necesariamente escrita exactamente en la misma forma)?
Rainbolt
1
@Rusher Es diferente. Por ejemplo, el número de invocaciones está codificado en la respuesta vinculada, mientras que aquí solo viene dado por la longitud del segundo argumento (que puede ser cualquier iterador).
Howard
1

Si está haciendo muchos reemplazos, podría hacer esto:

s=''.join({'H':'J','e':'i','l':'m','o':'y'}[a] for a in list(s))
TheDoctor
fuente
Esperaba una respuesta que no fuera específica para reemplazar. Acabo de usar eso como un ejemplo.
Rainbolt
Esto solo puede reemplazar 1 carácter a la vez, pero puede insertar reemplazos de múltiples caracteres. Y esto no está totalmente golfizado (elimine el espacio después [a])
Justin
2
¿No [a]tiene que ser reemplazado por .get(a,a)(de lo contrario, obtenemos algo de error clave)? ¿Y por qué tener en list(s)lugar de s?
Justin
1

¿Qué hay de definir una función 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
fuente
1
No es necesario: str.replace/ is / that lambda! Mira mi respuesta.
MtnViewMark
1

Si no es necesario encadenar sus reemplazos, puede usar `str.translate '. Los números son los ordinales ASCII. Usarlo de esta manera requiere Python 3:

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

Pruébalo en línea

mbomb007
fuente