Esta es una pregunta de consejos para jugar golf en Python.
En el golf de Python, es común que un envío sea una función definida como lambda. Por ejemplo,
f=lambda x:0**x or x*f(x-1)
calcula el factorial de x.
El formato lambda tiene dos grandes ventajas :
- La repetitiva de
f=lambda x:...
olambda x:...
es más corta que ladef f(x):...return...
ox=input()...print...
- Se puede usar una llamada recursiva para hacer un bucle con una pequeña sobrecarga de bytes.
Sin embargo, las lambdas tienen el gran inconveniente de permitir solo una sola expresión, sin declaraciones. En particular, esto significa que no hay tareas como c=chr(x+65)
. Esto es problemático cuando uno tiene una expresión larga cuyo valor necesita ser referenciado dos veces (o más).
Las asignaciones como E=enumerate
son posibles fuera de la función o como argumento opcional, pero solo si no dependen de las entradas de la función. Argumentos opcionales como f=lambda n,k=min(n,0):...
error porque la entrada n
no se ha definido cuando k
se evalúa en el momento de la definición.
El resultado es que a veces apestas repetir una expresión larga en una lambda porque la alternativa es una larga no lambda.
lambda s:s.strip()+s.strip()[::-1]
def f(s):t=s.strip();print t+t[::-1]
El punto de equilibrio es de aproximadamente 11 caracteres ( detalles ), pasado el cual cambia a un def
o program
. Compare esto con el punto de equilibrio habitual de longitud 5 para una expresión repetida:
range(a)+range(b)
r=range;r(a)+r(b)
print s[1:],s[1:]*2
r=s[1:];print r,r*2
Otros idiomas tienen soluciones alternativas, por ejemplo , Octave . Hay trucos conocidos para Python, pero son largos, torpes y / o de uso limitado. Un método breve y de propósito general para simular la asignación en una lambda revolucionaría el golf de Python.
¿Cuáles son las formas para que un golfista de Python supere o evite esta limitación? ¿Qué ideas potenciales deberían tener en mente cuando ven una expresión larga repetida dos veces en una lambda?
Mi objetivo con esta pregunta de consejos es profundizar en este problema y:
- Cataloga y analiza soluciones de golf para falsificar tareas dentro de una lambda
- Explore nuevos clientes potenciales para obtener mejores métodos
Cada respuesta debe explicar una solución alternativa o potencial cliente potencial.
lambda s:(s+s[::-1]).lower()
. Por supuesto, esto no responde la pregunta real.strip
.Respuestas:
eval
Esto no es tan bueno en sí mismo, pero si su solución ya se usa
eval
de alguna manera o forma, generalmente puede usar esta técnica.fuente
Expresiones de asignación en Python 3.8
Python 3.8 ( TIO ) introduce expresiones de asignación , que se utilizan
:=
para asignar una variable en línea como parte de la expresión.Esto se puede usar dentro de a
lambda
, donde las asignaciones no se permiten normalmente. Comparar:Vea este consejo para más.
fuente
Lambdas interiores
Estos le permiten definir múltiples variables a la vez.
vs.
es mucho más largo, pero si tiene múltiples variables, o variables que son más largas, que se repiten muchas veces:
vs.
Número de letras
Inicial:
(lambda:)()
(11 bytes)Primera variable:
[space]a
(2 bytes)Variables posteriores:
,b,
(3 bytes)Uso:
a
(1 byte).(También ahorra entre paréntesis)
Entonces, esto toma
3n + 10
bytes, donden
es el número de variables. Este es un alto costo inicial, pero puede pagar al final. Incluso devuelve su valor interno, por lo que puede anidar múltiples (aunque esto rápidamente no valdrá la pena).Esto realmente solo es útil para cálculos intermedios largos en comprensiones de listas anidadas, ya
def f():a=...;b=...;return
que generalmente será más corto.Para 1 valor, esto guarda:,
uses * length - length - uses - 13
por lo que solo es útil cuando esa expresión es positiva.Para
n
diferentes expresiones utilizadasu
en total, donde su longitud combinada esl
, esto guarda:l - (3 * n) - u - 10 ( + brackets removed )
fuente
Use una lista
Declarar una lista como parámetro y usar
.append() or
para almacenar el valor: selambda s:s.lower()+s.lower()[::-1]
convierte en
lambda s,l=[]:l.append(s.lower())or l[-1]+l[-1][::-1]
Número de letras:
,l=[]
5 caracteresl.append()or
13 caracteresl[-1]
5 caracteres para cada usoCubrir los gastos
La cantidad de caracteres añadidos es:
uses*(5-length) + 18 + length
en el ejemplo anterior, la declaración
s.lower()
tiene 9 caracteres de longitud y se usa 2 veces, aplicando esta técnica se agregaron 19 caracteres. Si se usara 7 veces, habría una reducción de 1 carácter.La cantidad de usos mínimos que vale esta técnica es
min_uses = (18+length)/(length-5)
Al revés
list
objeto de modo[0]
,.pop()
,[x:y]
y otras funciones de la lista se puede utilizar para hacer trucos. altamente situacionalDesventajas
5
Usa un diccionario
gracias @Zgarb
Misma idea que la anterior Declarar un diccionario como parámetro y usar
.setdefault()
para almacenar (y devolver) el valor: selambda s:s.lower()+s.lower()[::-1]
convierte en
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
Tenga en cuenta que, a diferencia de la
list
contraparte,setdefault
devuelve el valor asignado.Número de letras:
,d={}
5 caracteresd.setdefault(k,)
16 caracteresd[k]
4 caracteres para cada usoCubrir los gastos
La cantidad de caracteres agregados es:
(uses-1)*(4-length) + 21
En el ejemplo anterior, la declaración
s.lower()
tiene 9 caracteres de longitud y se usa 2 veces, aplicando esta técnica se agregaron 16 caracteres. Si se usara 7 veces, habría una reducción de 1 carácter.La cantidad de usos mínimos que vale esta técnica es
min_uses = 1-21/(4-length)
Ventajas / desventajas
4
Otras Consideraciones
lambda
probablemente se puede descartar y la función se puede reescribir condef
/input
para un programa más corto.fuente
lambda s,d={}:d.setdefault(0,s.lower())+d[0][::-1]
también es reutilizable.list.extend
para agregar varios elementos a la vez, lo que será más corto que usarlist.append
varias veces.Se usa para establecer variables y devolver los datos después de la operación de la siguiente manera:
fuente
Lista de comprensiones
Este es más un último recurso, ya que es muy infiel, pero puedes hacer
[<expression> for <variable> in <value>]
para seudo-establecer una variable en una lambda. Básicamente, el único punto bueno de este método es que la expresión interna puede seguir siendo legible, lo que obviamente es lo que menos le preocupa al jugar golf.
fuente