Ao codificar em outras linguagens, você às vezes criará um escopo de bloco, como este:
statement
...
statement
{
statement
...
statement
}
statement
...
statement
Um dos objetivos (de muitos) é melhorar a legibilidade do código: mostrar que certas instruções formam uma unidade lógica ou que certas variáveis locais são usadas apenas naquele bloco.
Existe uma maneira idiomática de fazer a mesma coisa em Python?
One purpose (of many) is to improve code readability
- O código Python, escrito corretamente (ou seja, seguindo o zen do python ) não precisa desse enfeite para ser legível. Na verdade, é uma das (muitas) coisas de que gosto no Python.__exit__
ewith
declaração, mudando oglobals()
mas eu falhei.Respostas:
Não, não há suporte de idioma para a criação de escopo de bloco.
As seguintes construções criam escopo:
fonte
A maneira idiomática em Python é manter suas funções curtas. Se você acha que precisa disso, refatore seu código! :)
Python cria um novo escopo para cada módulo, classe, função, expressão geradora, compreensão de dicionário, compreensão de conjunto e em Python 3.x também para cada compreensão de lista. Além desses, não há escopos aninhados dentro das funções.
fonte
Você pode fazer algo semelhante a um escopo de bloco C ++ em Python declarando uma função dentro de sua função e, em seguida, chamando-a imediatamente. Por exemplo:
Se você não tem certeza por que deseja fazer isso, este vídeo pode convencê-lo.
O princípio básico é definir o escopo de tudo o mais estreitamente possível, sem introduzir qualquer 'lixo' (tipos / funções extras) em um escopo mais amplo do que o absolutamente necessário - Nada mais deseja usar o
do_first_thing()
método, por exemplo, então ele não deve ter escopo fora do função de chamada.fonte
Eu concordo que não há escopo de bloco. Mas um lugar no python 3 o torna PARECIDO como se tivesse um escopo de bloco.
o que aconteceu que deu esse visual? Isso estava funcionando corretamente no python 2. mas para fazer o vazamento de variável parar no python 3, eles fizeram esse truque e essa mudança faz com que pareça que há um escopo de bloco aqui.
Deixe-me explicar.
Pela ideia de escopo, quando introduzimos variáveis com os mesmos nomes dentro do mesmo escopo, seu valor deve ser modificado.
isso é o que está acontecendo em python 2
Mas em python 3, embora a variável com o mesmo nome seja introduzida, ela não sobrescreve, a compreensão da lista age como uma caixa de areia por algum motivo e parece criar um novo escopo nela.
e essa resposta vai contra a declaração do respondente @Thomas. O único meio de criar escopo são funções, classes ou módulos, porque isso se parece com outro local de criação de um novo escopo.
fonte
Módulos (e pacotes) são uma ótima maneira Pythônica de dividir seu programa em namespaces separados, o que parece ser um objetivo implícito desta questão. Na verdade, enquanto estava aprendendo o básico do Python, me senti frustrado com a falta de um recurso de escopo de bloco. No entanto, uma vez que entendi os módulos Python, pude realizar com mais elegância meus objetivos anteriores sem a necessidade de escopo de bloco.
Como motivação, e para apontar as pessoas para a direção certa, acho que é útil fornecer exemplos explícitos de algumas das construções de escopo do Python. Primeiro, explico minha tentativa fracassada de usar classes Python para implementar o escopo do bloco. A seguir, explico como consegui algo mais útil usando módulos Python. No final, descrevo uma aplicação prática de pacotes para carregar e filtrar dados.
Tentando escopo de bloco com classes
Por alguns momentos, pensei que havia alcançado o escopo do bloco colocando o código dentro de uma declaração de classe:
Infelizmente, isso falha quando uma função é definida:
Isso ocorre porque as funções definidas em uma classe usam escopo global. A maneira mais fácil (embora não a única) de corrigir isso é especificar explicitamente a classe:
Isso não é tão elegante porque é preciso escrever funções de maneira diferente, dependendo se estão ou não contidas em uma classe.
Melhores resultados com módulos Python
Módulos são muito semelhantes às classes estáticas, mas os módulos são muito mais limpos na minha experiência. Para fazer o mesmo com os módulos, crio um arquivo chamado
my_module.py
no diretório de trabalho atual com o seguinte conteúdo:Então, em meu arquivo principal ou sessão interativa (por exemplo, Jupyter), eu faço
Como explicação, cada arquivo Python define um módulo que possui seu próprio namespace global. Importar um módulo permite que você acesse as variáveis neste namespace com o
.
sintaxe.Se você estiver trabalhando com módulos em uma sessão interativa, você pode executar essas duas linhas no início
e os módulos serão recarregados automaticamente quando seus arquivos correspondentes forem modificados.
Pacotes para carregar e filtrar dados
A ideia de pacotes é uma pequena extensão do conceito de módulos. Um pacote é um diretório que contém um
__init__.py
arquivo (possivelmente em branco) , que é executado na importação. Módulos / pacotes dentro deste diretório podem ser acessados com a.
sintaxe.Para análise de dados, geralmente preciso ler um grande arquivo de dados e, em seguida, aplicar interativamente vários filtros. Ler um arquivo leva vários minutos, então quero fazer isso apenas uma vez. Com base no que aprendi na escola sobre programação orientada a objetos, costumava acreditar que se deveria escrever o código para filtrar e carregar como métodos em uma classe. Uma grande desvantagem dessa abordagem é que, se eu redefinir meus filtros, a definição de minha classe muda, então tenho que recarregar a classe inteira, incluindo os dados.
Hoje em dia com Python, defino um pacote chamado
my_data
que contém submódulos chamadosload
efilter
. Dentro defilter.py
eu posso fazer uma importação relativa:Se eu modificar
filter.py
,autoreload
detectarei as mudanças. Ele não recarregaload.py
, então não preciso recarregar meus dados. Dessa forma, posso criar um protótipo de meu código de filtragem em um bloco de notas Jupyter, envolvê-lo como uma função e, em seguida, cortar e colar de meu bloco de notas diretamente nofilter.py
. Descobrir isso revolucionou meu fluxo de trabalho e me transformou de um cético em um crente no "Zen de Python".fonte