Respostas:
Isso não tem nada a ver com Python; variáveis globais são ruins em qualquer linguagem de programação.
No entanto, constantes globais não são conceitualmente iguais às variáveis globais ; constantes globais são perfeitamente inofensivas. Em Python, a distinção entre os dois é puramente por convenção: CONSTANTS_ARE_CAPITALIZED
e globals_are_not
.
A razão pela qual as variáveis globais são ruins é que elas permitem que funções tenham efeitos colaterais ocultos (não óbvios, surpreendentes, difíceis de detectar, difíceis de diagnosticar), levando a um aumento na complexidade, potencialmente levando ao código Spaghetti .
No entanto, o uso racional do estado global é aceitável (assim como o estado local e a mutabilidade), mesmo em programação funcional, seja para otimização de algoritmo, complexidade reduzida, armazenamento em cache e memoização, ou a praticidade de portar estruturas originadas em uma base de código predominantemente imperativa.
Resumindo, sua pergunta pode ser respondida de várias maneiras, então sua melhor aposta é apenas pesquisar no Google "por que as variáveis globais são ruins". Alguns exemplos:
Se você quiser se aprofundar e descobrir por que os efeitos colaterais estão relacionados e muitas outras coisas esclarecedoras, você deve aprender Programação Funcional:
Sim, em teoria , os globais (e o "estado" em geral) são maus. Na prática, se você olhar para o diretório de pacotes do python, você descobrirá que a maioria dos módulos lá começa com um monte de declarações globais. Obviamente, as pessoas não têm problemas com eles.
Especificamente para python, a visibilidade global é limitada a um módulo, portanto, não existem globais "verdadeiros" que afetam todo o programa - o que os torna menos prejudiciais. Outro ponto: não há const
, então quando você precisa de uma constante, você tem que usar uma global.
Na minha prática, se acontecer de eu modificar um global em uma função, sempre declaro isso com global
, mesmo que tecnicamente não haja necessidade disso, como em:
cache = {}
def foo(args):
global cache
cache[args] = ...
Isso torna as manipulações globais mais fáceis de rastrear.
Uma opinião pessoal sobre o assunto é que ter variáveis globais sendo usadas em uma lógica de função significa que algum outro código pode alterar a lógica e a saída esperada dessa função, o que tornará a depuração muito difícil (especialmente em grandes projetos) e tornará os testes mais difíceis também.
Além disso, se você considerar outras pessoas lendo seu código (comunidade de código aberto, colegas, etc.), elas terão dificuldade em entender onde a variável global está sendo definida, onde foi alterada e o que esperar dessa variável global. para uma função isolada que sua funcionalidade pode ser determinada pela leitura da própria definição da função.
Acredito que um código limpo e (quase) sem bugs deve ter funções tão puras quanto possível (consulte funções puras ). Uma função pura é aquela que possui as seguintes condições:
Ter variáveis globais está violando pelo menos um dos itens acima, se não ambos, pois um código externo pode provavelmente causar resultados inesperados.
Outra definição clara de funções puras: "Função pura é uma função que recebe todas as suas entradas como argumentos explícitos e produz todas as suas saídas como resultados explícitos ." [1] . Ter variáveis globais viola a ideia de funções puras, uma vez que uma entrada e talvez uma das saídas (a variável global) não está sendo explicitamente fornecida ou retornada.
Mais adiante que, se você considerar teste de unidade e o primeiro princípio ( F testes AST, I testes ndependent, R epeatable, S elf-Validação e T imely) provavelmente irá violar testa princípio (o Independent o que significa que os testes não dependem um no outro).
Ter uma variável global (nem sempre), mas na maioria dos casos (pelo menos do que vi até agora) é preparar e passar os resultados para outras funções. Isso também viola esse princípio. Se a variável global foi usada dessa maneira (ou seja, a variável global usada na função X deve ser definida em uma função Y primeiro), significa que para a função de teste de unidade X você deve executar o teste / a função Y primeiro.
Por outro lado e como outras pessoas já mencionaram, se a variável global for usada como uma variável "constante" pode ser um pouco melhor, pois a linguagem não suporta constantes. No entanto, sempre prefiro trabalhar com classes e ter as "constantes" como um membro da classe e não usar uma variável global. Se você tiver um código que duas classes diferentes requerem para compartilhar uma variável global, provavelmente precisará refatorar sua solução e tornar suas classes independentes.
Não acredito que os globais não devam ser usados. Mas, se forem usados, os autores devem considerar alguns princípios (talvez os mencionados acima e outros princípios e boas práticas de engenharia de software) para um código mais limpo e quase livre de erros.
Eles são essenciais, a tela é um bom exemplo. No entanto, em um ambiente multithread ou com muitos desenvolvedores envolvidos, na prática muitas vezes surge a pergunta: quem o definiu ou apagou (erroneamente)? Dependendo da arquitetura, a análise pode ser cara e frequentemente necessária. Enquanto a leitura da var global pode ser boa, a gravação nela deve ser controlada, por exemplo, por um único thread ou classe threadsafe. Conseqüentemente, os vars globais levantam o medo de altos custos de desenvolvimento possíveis pelas consequências pelas quais são considerados maléficos. Portanto, em geral, é uma boa prática manter baixo o número de vars globais.
eval
,import *
, concatenação , variávelid
, sombras atributo )