Respuestas:
Esto no tiene nada que ver con Python; las variables globales son malas en cualquier lenguaje de programación.
Sin embargo, las constantes globales no son conceptualmente las mismas que las variables globales ; las constantes globales son perfectamente inofensivas. En Python, la distinción entre los dos es puramente por convención: CONSTANTS_ARE_CAPITALIZED
y globals_are_not
.
La razón por la que las variables globales son malas es que permiten que las funciones tengan efectos secundarios ocultos (no obvios, sorprendentes, difíciles de detectar, difíciles de diagnosticar), lo que lleva a un aumento en la complejidad, lo que potencialmente conduce al código Spaghetti .
Sin embargo, el uso sensato del estado global es aceptable (al igual que el estado local y la mutabilidad) incluso en la programación funcional, ya sea para optimización de algoritmos, complejidad reducida, almacenamiento en caché y memorización, o la practicidad de portar estructuras que se originan en una base de código predominantemente imperativa.
En general, su pregunta puede responderse de muchas maneras, por lo que su mejor opción es simplemente buscar en Google "por qué las variables globales son malas". Algunos ejemplos:
Si desea profundizar y descubrir por qué se tratan los efectos secundarios y muchas otras cosas esclarecedoras, debe aprender Programación funcional:
Sí, en teoría , los globales (y el "estado" en general) son malvados. En la práctica, si busca en el directorio de paquetes de su python, encontrará que la mayoría de los módulos comienzan con un montón de declaraciones globales. Evidentemente, la gente no tiene ningún problema con ellos.
Específicamente para Python, la visibilidad de los globales se limita a un módulo, por lo tanto, no hay globales "verdaderos" que afecten a todo el programa, lo que los hace menos dañinos. Otro punto: no hay const
, así que cuando necesitas una constante tienes que usar una global.
En mi práctica, si modifico un global en una función, siempre lo declaro con global
, incluso si técnicamente no hay necesidad de eso, como en:
cache = {}
def foo(args):
global cache
cache[args] = ...
Esto hace que las manipulaciones globales sean más fáciles de rastrear.
Una opinión personal sobre el tema es que el uso de variables globales en la lógica de una función significa que algún otro código puede alterar la lógica y la salida esperada de esa función, lo que hará que la depuración sea muy difícil (especialmente en proyectos grandes) y dificultará las pruebas. también.
Además, si considera que otras personas leen su código (comunidad de código abierto, colegas, etc.), tendrán dificultades para tratar de comprender dónde se establece la variable global, dónde se ha cambiado y qué esperar de esta variable global en lugar de a una función aislada que su funcionalidad se puede determinar leyendo la propia definición de función.
Creo que un código limpio y (casi) libre de errores debería tener funciones lo más puras posible (ver funciones puras ). Una función pura es aquella que tiene las siguientes condiciones:
Tener variables globales es violar al menos una de las anteriores, si no ambas, ya que un código externo probablemente puede causar resultados inesperados.
Otra definición clara de funciones puras: "La función pura es una función que toma todas sus entradas como argumentos explícitos y produce todas sus salidas como resultados explícitos ". [1] . Tener variables globales viola la idea de funciones puras ya que una entrada y tal vez una de las salidas (la variable global) no se da ni se devuelve explícitamente.
Además de eso, si se tiene en cuenta la unidad de pruebas y el primer principio ( F pruebas AST, I pruebas ndependent, R epeatable, S Elf-Validar y T imely) probablemente violaría el principio independiente de prueba (lo que significa que las pruebas no dependen el uno del otro).
Tener una variable global (no siempre) pero en la mayoría de los casos (al menos de lo que he visto hasta ahora) es preparar y pasar resultados a otras funciones. Esto también viola este principio. Si la variable global se ha utilizado de esa forma (es decir, la variable global utilizada en la función X debe configurarse primero en una función Y), significa que para probar unitariamente la función X, primero debe ejecutar la función de prueba / ejecución Y.
Por otro lado y como ya han comentado otras personas, si se utiliza la variable global como variable "constante" puede ser algo mejor ya que el lenguaje no soporta constantes. Sin embargo, siempre prefiero trabajar con clases y tener las "constantes" como miembro de la clase y no usar una variable global en absoluto. Si tiene un código que dos clases diferentes requieren para compartir una variable global, entonces probablemente necesite refactorizar su solución y hacer que sus clases sean independientes.
No creo que no se deban utilizar globales. Pero si se utilizan, los autores deberían considerar algunos principios (los mencionados anteriormente, quizás, y otros principios y buenas prácticas de ingeniería de software) para un código más limpio y casi libre de errores.
Son imprescindibles, siendo la pantalla un buen ejemplo. Sin embargo, en un entorno multiproceso o con muchos desarrolladores involucrados, en la práctica a menudo surge la pregunta: ¿quién lo configuró (erróneamente) o lo borró? Dependiendo de la arquitectura, el análisis puede resultar costoso y ser necesario con frecuencia. Si bien la lectura de la var global puede estar bien, la escritura debe ser controlada, por ejemplo, por un solo hilo o una clase segura para hilos. De ahí que las vars globales surjan el temor a los altos costos de desarrollo posibles por las consecuencias por las cuales ellos mismos son considerados malvados. Por lo tanto, en general, es una buena práctica mantener bajo el número de variables globales.
eval
,import *
, la concatenación de cadenas , variablesid
, sombras de atributos )