Pergunta

Recebo esse aviso pep8 sempre que uso expressões lambda.As expressões lambda não são recomendadas?Se não, por que?

Foi útil?

Solução

A recomendação em PEP-8 você está encontrando é:

Sempre use uma instrução DEF em vez de uma declaração de atribuição que vincule uma expressão lambda diretamente a um nome.

Sim:

def f(x): return 2*x 

Não:

f = lambda x: 2*x 

O primeiro formulário significa que o nome do objeto de função resultante é especificamente 'f' em vez do genérico 'u003Clambda> '.Isso é mais útil para rastreios e representações de cordas em geral.O uso da declaração de atribuição elimina o único benefício que uma expressão de lambda pode oferecer sobre uma declaração explícita de def (ou sejaque pode ser incorporado dentro de uma expressão maior)

Atribuir lambdas a nomes basicamente apenas duplica a funcionalidade de def - e em geral, é melhor fazer algo de uma única maneira para evitar confusão e aumentar a clareza.

O caso de uso legítimo para lambda é onde você deseja usar uma função sem atribuí-la, por exemplo:

sorted(players, key=lambda player: player.rank)

Para operações simples, o operator módulo fornece algumas opções úteis em attrgetter, itemgetter e methodcaller que muitas vezes pode substituir labmdas que estão apenas acessando atributos, itens e métodos de chamada.

Por exemplo, o procedimento acima poderia ser feito com operator.attrgetter igual a:

sorted(players, key=operator.attrgetter('rank'))

Outras dicas

Aqui está a história: eu tinha uma função lambda simples que usei duas vezes.

a = map(lambda x : x + offset, simple_list)
b = map(lambda x : x + offset, another_simple_list)

Isso é apenas para representação, já enfrentei algumas versões diferentes disso.

Agora, para manter as coisas SECAS, começo a reutilizar esse lambda comum.

f = lambda x : x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

Neste ponto, meu verificador de qualidade de código reclama que lambda é uma função nomeada, então eu o converto em uma função.

def f(x):
    return x + offset
a = map(f, simple_list)
b = map(f, another_simple_list)

Agora o verificador reclama que uma função deve ser delimitada por uma linha em branco antes e depois.

def f(x):
    return x + offset

a = map(f, simple_list)
b = map(f, another_simple_list)

Aqui temos agora 6 linhas de código em vez das 2 linhas originais, sem aumento na legibilidade e sem aumento em pythônico.Neste ponto, o verificador de código reclama que a função não possui docstrings.

Na minha opinião, é melhor evitar e quebrar esta regra quando fizer sentido, use seu bom senso.

Lattyware está absolutamente certo:Basicamente PEP-8 quer que você evite coisas como

f = lambda x: 2 * x

e em vez disso use

def f(x):
    return 2 * x

Contudo, conforme abordado em recente relatório de erro (agosto de 2014), declarações como as seguintes agora estão em conformidade:

a.f = lambda x: 2 * x
a["f"] = lambda x: 2 * x

Como meu verificador PEP-8 ainda não implementou isso corretamente, desliguei o E731 por enquanto.

Também encontrei uma situação em que era impossível usar uma função 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},
  }

Nesse caso, eu queria muito fazer um mapeamento que pertencesse à classe.Alguns objetos no mapeamento precisavam da mesma função.Seria ilógico colocar a função nomeada fora da classe.Não encontrei uma maneira de me referir a um método (staticmethod, classmethod ou normal) de dentro do corpo da classe.SomeClass ainda não existe quando o código é executado.Portanto, referir-se a isso na classe também não é possível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top