Por que os geradores e funções python compartilham a palavra-chave “def”?


10

Considere o seguinte:

def some_function():
    return 1

def some_generator():
    yield 1

No código acima, some_functioné uma função, enquanto some_generatoré um gerador. Eles parecem bastante semelhantes.

O problema que tenho ao ler o código é que preciso varrer todas as linhas de uma "função" procurando a yieldpalavra - chave antes de poder determinar se é realmente uma função ou um gerador!

Parece-me que usar uma palavra-chave diferente para geradores faria mais sentido, por exemplo:

gen some_generator():
    yield 1

Quais são os méritos de usar a defpalavra - chave para geradores e funções? Por que uma nova palavra-chave não foi introduzida para separar funções e geradores?


Não sei a resposta real, mas geralmente começo escrevendo funções que retornam listas e depois as converto em geradores quando parece certo. Ter a correspondência de sintaxe torna isso mais natural.
Gort the Robot

2
@StevenBurnap A sugestão de Derek de usar algo como em genvez de defnão tornaria essa transformação significativamente mais onerosa.
jamesdlin

2
Em geral, os designers de idiomas geralmente tentam evitar adicionar palavras-chave desnecessárias. Cada palavra-chave que eles adicionam é um identificador que os programas não têm permissão para usar para outros fins.
jamesdlin

@ jamesdlin: Mas a questão é argumentar que uma nova palavra-chave seria necessária .
Giorgio

1
@ jamesdlin: É claro que você pode distinguir funções e geradores olhando o corpo deles, mas a pergunta argumenta que o uso de palavras-chave diferentes tornaria o código mais legível.
Giorgio

Respostas:


14

"Quais são os méritos de usar a palavra-chave def para geradores e funções?"

Embora eles sejam mecanicamente diferentes, na prática, quando eu os uso, eles geralmente são efetivamente os mesmos para mim conceitualmente (não penso muito em chamar range()vs xrange()).

No entanto, em termos de compreensão rápida do que é a função, concordo que algo se perca com o uso de def, mas as coisas não devem ser muito ofuscadas dentro da função para começar.

Mesmo um implícito return Nonepode confundir o comportamento pretendido de uma função depois de um longo período de condicionais (como em, era return Nonepretendido como um comportamento final ou uma supervisão na lógica). Mas essas são apenas minhas crenças sobre isso.

Eu não acho que meu argumento seja particularmente convincente, portanto, irei adiar para o PEP 255 :

Problema: introduza outra nova palavra-chave (por exemplo, "gen" ou "gerador") no lugar de "def" ou altere a sintaxe para distinguir as funções de gerador das funções de não gerador.

Contras: Na prática (como você pensa sobre eles), geradores são funções, mas com a reviravolta de que podem ser retomados. A mecânica de como eles são configurados é uma questão técnica comparativamente menor, e a introdução de uma nova palavra-chave enfatizaria demais a mecânica de como os geradores são iniciados (uma parte vital, mas minúscula, da vida de um gerador).

Pro: Na realidade (como você pensa sobre eles), funções geradoras são na verdade funções de fábrica que produzem iteradores geradores como se por mágica. Nesse aspecto, eles são radicalmente diferentes das funções que não são geradoras, agindo mais como construtor do que como função, portanto, reutilizar "def" é, na melhor das hipóteses, confuso. Uma declaração de "rendimento" enterrada no corpo não é suficiente para avisar que a semântica é tão diferente.

BDFL: "def" permanece. Como nenhum argumento de ambos os lados é totalmente convincente, consultei a intuição do meu designer de linguagem. Diz-me que a sintaxe proposta no PEP é exatamente correta - nem muito quente nem muito fria. Mas, como o Oracle em Delphi na mitologia grega, ele não me diz o porquê, então eu não sou contra os argumentos contra a sintaxe do PEP. O melhor que posso encontrar (além de concordar com as refutações ... já feitas) é "FUD". Se isso fizesse parte da linguagem desde o primeiro dia, duvido muito que tivesse sido a página "Python Warts" de Andrew Kuchling.


1
Vale a pena notar que as novas await(e async withe async for) construções de sintaxe adicionados no PEP 492 , que funcionam muito semelhante ao yield from, exigem a função que está acostumado em ser declarado usando async defem vez de um apenas def.
Feuermurmel

2
  1. A adição de novas palavras-chave corre o risco de quebrar os programas existentes. Os designers de idiomas geralmente tentam evitar adicionar novas palavras-chave, especialmente para os recursos de idioma adicionados depois que o idioma já ganhou popularidade. Cada palavra-chave que eles adicionam é um identificador que os programas não têm permissão para usar para outros fins, portanto, a adição de uma palavra-chave pode potencialmente interromper os programas existentes. Os designers de idiomas precisam avaliar os benefícios de uma nova palavra-chave em relação aos custos.

  2. Duvido que definir uma palavra-chave separada para geradores traria muitos benefícios. Entender se um símbolo corresponde ao nome de uma função ou ao nome de um gerador é algo importante para os chamadores, e os chamadores não devem (e às vezes não podem) olhar para qual palavra-chave foi usada para implementá-la. Essa é a responsabilidade de melhores convenções e documentação de nomes.


1

Geradores são funções que avaliam preguiçosamente. Dado que eles são a mesma coisa na base, faz sentido que eles usem a mesma palavra-chave. Uma opção pode ser usar um comentário para identificar qual é qual para uma determinada instância:

def some_function(): #This is a function.
    return 1

def some_generator(): #This is a generator.
    yield 1

0

Eu acho que é porque é mais pitônico, mas o que eu sei? ;)

Eu realmente não acho que isso importe muito. É mais fácil lembrar para mim, porque não há necessidade de memorizar os dois.

EDIT: O PEP pode dizer, você pode investigar lá.


Obrigado! De fato, o PEP diz! Consulte PEP-255 para obter os prós / contras e a decisão final sobre uma nova palavra-chave para geradores.
Derek Kwok

Com significado pitônico: "Como é feito em Python"?
Giorgio
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.