Exemplo simples. Dois métodos, um chamado de outro:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
Em Python, podemos declarar def
dentro de outro def
. Então, se method_b
for necessário e chamado apenas de method_a
, devo declarar method_b
dentro method_a
? como isso :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Ou devo evitar fazer isso?
python
coding-style
nukl
fonte
fonte
method_b
? (@inspector: Você precisa, estritamente falando, mas é imensamente útil quando você entra em um pouco de programação funcional, em especial fechamentos).Respostas:
Não era isso que você estava procurando? É chamado de fechamento .
fonte
do_it()
que presumivelmente seria um pouco mais complicado do que o que pode ser tratado por alguma aritmética em uma únicareturn
declaração.Você não ganha muito fazendo isso, na verdade, fica mais lento
method_a
porque define e recompila a outra função toda vez que é chamada. Dado isso, provavelmente seria melhor prefixar o nome da função com sublinhado para indicar que é um método privado - ou seja_method_b
.Eu suponho que você pode querer fazer isso se a definição da função aninhada variado cada vez, por algum motivo, mas isso pode indicar uma falha em seu projeto. Dito isto, não é uma razão válida para fazer isso para permitir que a função aninhada de usar argumentos que foram passados para a função externa, mas não passaram explicitamente a eles, o que por vezes ocorre quando se escreve decoradores de função, por exemplo. É o que está sendo mostrado na resposta aceita, embora um decorador não esteja sendo definido ou usado.
Atualizar:
Aqui está a prova de que o aninhamento é mais lento (usando o Python 3.6.1), embora, reconhecidamente, não seja muito neste caso trivial:
Observe que adicionei alguns
self
argumentos às suas funções de amostra para torná-las mais parecidas com métodos reais (emboramethod_b2
ainda não seja tecnicamente um método daTest
classe). Além disso, a função aninhada é realmente chamada nessa versão, diferente da sua.fonte
method_b = self._method_b
e depois liguemethod_b
para evitar as repetidas pesquisas de atributo. (Acontece que eu tenho feito MUITO tempo ultimamente. :)Uma função dentro de uma função é comumente usada para fechamentos .
(Há muita controvérsia sobre o que exatamente faz de um fechamento um fechamento .)
Aqui está um exemplo usando o built-in
sum()
. Ele definestart
uma vez e o utiliza a partir de então:Em uso:
Fechamento python embutido
functools.partial
é um exemplo de fechamento.Nos documentos python , é aproximadamente equivalente a:
(Parabéns a @ user225312 abaixo para obter a resposta. Acho este exemplo mais fácil de descobrir e espero ajudar a responder o comentário de @ mango.)
fonte
Geralmente, não, não define funções dentro de funções.
A menos que você tenha uma boa razão. O que você não faz.
Por que não?
lambda
expressão .Qual é realmente uma boa razão para definir funções dentro de funções?
Quando o que você realmente quer é um fechamento bobo .
fonte
É realmente bom declarar uma função dentro de outra. Isso é especialmente útil para criar decoradores.
No entanto, como regra geral, se a função for complexa (mais de 10 linhas), pode ser uma ideia melhor declará-la no nível do módulo.
fonte
Eu encontrei essa pergunta porque queria fazer uma pergunta por que há um impacto no desempenho se alguém usa funções aninhadas. Eu executei testes para as seguintes funções usando o Python 3.2.5 em um notebook Windows com um processador Intel Core i5-2530M de 2,5 GHz e quatro núcleos
Eu medi as seguintes 20 vezes, também para quadrado1, quadrado2 e quadrado5:
e obteve os seguintes resultados
square0
não possui função aninhada,square1
possui uma função aninhada,square2
possui duas funções aninhadas esquare5
possui cinco funções aninhadas. As funções aninhadas são declaradas apenas, mas não chamadas.Portanto, se você definiu 5 funções aninhadas em uma função que você não chama, o tempo de execução da função é o dobro da função sem uma função aninhada. Eu acho que deve ser cauteloso ao usar funções aninhadas.
O arquivo Python para todo o teste que gera essa saída pode ser encontrado em ideone .
fonte
É apenas um princípio sobre APIs de exposição.
Usando python, é uma boa idéia evitar a API de exposição no espaço sideral (módulo ou classe), a função é um bom local de encapsulamento.
Poderia ser uma boa ideia. quando você garantir
Mesmo assim, o abuso dessa técnica pode causar problemas e implica uma falha de design.
Apenas da minha exp, talvez não entenda sua pergunta.
fonte
Portanto, no final, é em grande parte uma questão sobre o quão inteligente é ou não a implementação do python, particularmente no caso da função interna não ser um fechamento, mas simplesmente uma função in necessária apenas para auxiliar.
No design compreensível e limpo, com funções apenas onde são necessárias e não expostas a outros lugares, é bom design, sejam elas incorporadas a um módulo, uma classe como método ou dentro de outra função ou método. Quando bem feitos, eles realmente melhoram a clareza do código.
E quando a função interna é um fechamento, também pode ajudar bastante com clareza, mesmo que essa função não seja retornada da função que o contém para uso em outros lugares.
Então, eu diria que geralmente os utiliza, mas esteja ciente do possível impacto no desempenho quando você estiver realmente preocupado com o desempenho e os remova somente se você criar um perfil real que mostre que é melhor removê-los.
Não faça otimização prematura usando apenas "funções internas BAD" em todo o código python que você escreve. Por favor.
fonte
Não há problema em fazê-lo dessa maneira, mas, a menos que você precise usar um fechamento ou retornar a função que eu provavelmente colocaria no nível do módulo. Eu imagino no segundo exemplo de código que você quer dizer:
caso contrário, some_data será a função.
Tê-lo no nível do módulo permitirá que outras funções usem method_b () e se você estiver usando algo como Sphinx (e autodoc) para documentação, permitirá que você documente também method_b.
Você também pode considerar apenas colocar a funcionalidade em dois métodos em uma classe se estiver fazendo algo que possa ser representável por um objeto. Isso também contém lógica, se é tudo o que você procura.
fonte
Faça algo como:
se você executasse,
some_function()
ele executariasome_other_function()
e retornaria 42.Edição: Eu originalmente afirmei que você não deve definir uma função dentro de outra, mas foi apontado que é prático fazer isso algumas vezes.
fonte
Você pode usá-lo para evitar a definição de variáveis globais. Isso oferece uma alternativa para outros designs. 3 projetos apresentando uma solução para um problema.
A) Usando funções sem globais
B) Usando funções com globais
C) Usando funções dentro de outra função
A solução C) permite usar variáveis no escopo da função externa sem a necessidade de declará-las na função interna. Pode ser útil em algumas situações.
fonte
Função Na função python
fonte