python - curso - E731 no asigna una expresión lambda, use un def
expresiones lambda java (5)
Aquí está la historia, tenía una función lambda simple que estaba usando dos veces.
a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)
Esto es solo para la representación, he enfrentado un par de versiones diferentes de esto.
Ahora, para mantener las cosas SECAS, empiezo a reutilizar esta lambda común.
f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
En este momento mi verificador de calidad de código se queja de que lambda es una función nombrada, así que la convierto en una función.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Ahora el verificador se queja de que una función tiene que estar delimitada por una línea en blanco antes y después.
def f(x):
return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)
Aquí tenemos ahora 6 líneas de código en lugar de 2 líneas originales sin aumento en la legibilidad y sin aumento en ser pitónico. En este punto, el verificador de código se queja de que la función no tiene cadenas de documentos.
En mi opinión, esta regla es mejor evitarla y romperla cuando tenga sentido, use su juicio.
Recibo esta advertencia de pep8 cada vez que uso expresiones lambda. ¿No se recomiendan las expresiones lambda? Si no, ¿por qué?
La recomendación en PEP-8 que se está encontrando es:
Utilice siempre una instrucción def en lugar de una declaración de asignación que una expresión lambda directamente a un nombre.
Sí:
def f(x): return 2*x
No:
f = lambda x: 2*x
La primera forma significa que el nombre del objeto de función resultante es específicamente ''f'' en lugar del genérico ''<lambda>''. Esto es más útil para los trazados y las representaciones de cadenas en general. El uso de la declaración de asignación elimina el único beneficio que una expresión lambda puede ofrecer sobre una declaración de def explícita (es decir, que puede incrustarse dentro de una expresión más grande)
Asignar lambdas a nombres básicamente solo duplica la funcionalidad de def
- y, en general, es mejor hacer algo de una sola manera para evitar confusiones y aumentar la claridad.
El caso de uso legítimo para lambda es donde desea utilizar una función sin asignarla, por ejemplo:
sorted(players, key=lambda player: player.rank)
Para operaciones simples, el módulo de operator
proporciona algunas opciones útiles en attrgetter
, itemgetter
y methodcaller
que a menudo pueden reemplazar labmdas que solo están accediendo a atributo (s), elemento (s) y métodos de llamada.
Por ejemplo, lo anterior se puede hacer con operator.attrgetter
como tal:
sorted(players, key=operator.attrgetter(''rank''))
Lambdas puede usarse para evaluaciones perezosas, posponiendo ciertas operaciones costosas hasta que realmente se necesiten sus resultados.
Acabo de encontrarme con un caso (en un concurso de código / problema de práctica) en el que estaba calculando funciones pow () relativamente caras (relativamente caras, ya que la entrada consistía en medio millón de casos de prueba) para 3 casos diferentes y ciertas combinaciones de los 3 casos. Para la claridad del código, calcularía los 3 casos y luego devolvería la combinación de los 3 que realmente se necesitaban para la solicitud actual.
Desafortunadamente, esto generaba un TLE ("límite de tiempo excedido") en ciertas entradas.
Al utilizar las lambdas para diferir las costosas operaciones de pow (), pude resolver problemas de TLE, ya que solo se invocaban los cálculos que eran relevantes para la solicitud actual.
Así que creo que este es un caso en el que la advertencia E731 no es realmente aplicable y debería ser desactivada.
Lattyware tiene toda la razón: Básicamente PEP-8 quiere que evites cosas como
f = lambda x: 2 * x
y en su lugar use
def f(x):
return 2 * x
Sin embargo, como se abordó en un bugreport reciente (agosto de 2014), las declaraciones como las siguientes ahora son compatibles:
a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x
Dado que mi comprobador PEP-8 aún no implementa esto correctamente, apagué el E731 por el momento.
También encontré una situación en la que era incluso imposible usar una función def (ined).
class SomeClass(object):
# pep-8 does not allow this
f = lambda x: x + 1 # NOQA
def not_reachable(self, x):
return x + 1
@staticmethod
def also_not_reachable(x):
return x + 1
@classmethod
def also_not_reachable(cls, x):
return x + 1
some_mapping = {
''object1'': {''name'': "Object 1", ''func'': f},
''object2'': {''name'': "Object 2", ''func'': some_other_func},
}
En este caso, realmente quería hacer un mapeo que perteneciera a la clase. Algunos objetos en el mapeo necesitaban la misma función. Sería ilógico colocar la función nombrada fuera de la clase. No he encontrado una manera de referirme a un método (método estático, método de clase o normal) desde dentro del cuerpo de la clase. SomeClass aún no existe cuando se ejecuta el código. Así que no es posible referirse a ella desde la clase tampoco.