Perché le variabili globali sono cattive? [chiuso]


121

Sto cercando di scoprire perché l'uso di globalè considerato una cattiva pratica in Python (e nella programmazione in generale). Qualcuno può spiegare? Sarebbero apprezzati anche collegamenti con maggiori informazioni.


Votazione per riaprire - Ho modificato la domanda per spostare l'attenzione sulle spiegazioni e lontano dalle risorse fuori sede. (Suppongo è per questo che è stato chiuso, ma solo nel caso che sia qualcosa a che fare con l'essere una domanda sul cattiva pratica, confrontare questi altre domande sulle cattive pratiche che sono ancora aperte: eval, import *, concatenazione di stringhe , variabiliid , le ombre degli attributi )
wjandrea

Risposte:


156

Questo non ha nulla a che fare con Python; le variabili globali sono cattive in qualsiasi linguaggio di programmazione.

Tuttavia, le costanti globali non sono concettualmente le stesse delle variabili globali ; le costanti globali sono perfettamente innocue. In Python la distinzione tra i due è puramente convenzionale: CONSTANTS_ARE_CAPITALIZEDe globals_are_not.

Il motivo per cui le variabili globali sono cattive è che consentono alle funzioni di avere effetti collaterali nascosti (non ovvi, sorprendenti, difficili da rilevare, difficili da diagnosticare), portando a un aumento della complessità, portando potenzialmente al codice Spaghetti .

Tuttavia, un uso sano dello stato globale è accettabile (così come lo stato locale e la mutabilità) anche nella programmazione funzionale, sia per l'ottimizzazione dell'algoritmo, la complessità ridotta, la memorizzazione nella cache e la memoizzazione, sia per la praticità delle strutture di porting originate da una base di codice prevalentemente imperativa.

Tutto sommato, è possibile rispondere alla tua domanda in molti modi, quindi la soluzione migliore è semplicemente cercare su Google "perché le variabili globali sono cattive". Qualche esempio:

Se vuoi andare più a fondo e scoprire perché sono tutti gli effetti collaterali e molte altre cose illuminanti, dovresti imparare la Programmazione Funzionale:


35

Sì, in teoria , i globali (e lo "stato" in generale) sono il male. In pratica, se guardi nella directory dei pacchetti del tuo python, scoprirai che la maggior parte dei moduli inizia con un mucchio di dichiarazioni globali. Ovviamente, le persone non hanno problemi con loro.

In particolare per Python, la visibilità delle globali è limitata a un modulo, quindi non ci sono globali "vere" che influenzano l'intero programma, il che le rende meno dannose. Un altro punto: non ce ne sono const, quindi quando hai bisogno di una costante devi usare una globale.

Nella mia pratica, se mi capita di modificare un globale in una funzione, lo dichiaro sempre con global, anche se tecnicamente non ce n'è bisogno, come in:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Questo rende le manipolazioni delle variabili globali più facili da rintracciare.


3
in molti modi, un modulo in python è simile a una classe singleton e le variabili globali del modulo sono simili alle proprietà della classe.
Corley Brigman

9
@CorleyBrigman: le classi singleton in realtà spesso soffrono degli stessi problemi tipicamente attribuiti ai globali :)
Erik Kaplun

4
la visibilità dei moduli python non è limitata a un modulo. Sono disponibili nell'intero interprete e (ecco la cosa importante) le modifiche influiscono sull'intero interprete. Non è come una stringa che crei istanze ... è come modificare tutte le istanze di stringa. Odore di patch di scimmia.
Graffic

2
La maggior parte dei moduli non inizia con la definizione di globali eccetto le costanti. I globali sono cattivi significa che le variabili / lo stato globale non sono costanti.
BlackJack

2
Usare le variabili globali è un'idea orribile, una delle ragioni potrebbe essere l'incapacità di testare adeguatamente le funzioni che aggiornano un dizionario arbitrario che esiste "da qualche parte". Una base di codice con globali non può essere effettivamente dimostrata funzionale.
Tomasz Sosiński

10

Un'opinione personale sull'argomento è che avere variabili globali utilizzate in una logica di funzione significa che qualche altro codice può alterare la logica e l'output atteso di quella funzione che renderà il debug molto difficile (specialmente nei grandi progetti) e renderà più difficili i test anche.

Inoltre, se consideri che altre persone leggano il tuo codice (comunità open source, colleghi ecc.), Avranno difficoltà a capire dove è stata impostata la variabile globale, dove è stata modificata e cosa aspettarsi da questa variabile globale al contrario a una funzione isolata che la sua funzionalità può essere determinata leggendo la definizione della funzione stessa.

(Probabilmente) Violazione della definizione di funzione pura

Credo che un codice pulito e (quasi) privo di bug dovrebbe avere funzioni quanto più pure possibili (vedere funzioni pure ). Una funzione pura è quella che presenta le seguenti condizioni:

  1. La funzione valuta sempre lo stesso valore di risultato dato gli stessi valori di argomento . Il valore del risultato della funzione non può dipendere da informazioni o stati nascosti che possono cambiare durante l'esecuzione del programma o tra diverse esecuzioni del programma, né può dipendere da alcun input esterno dai dispositivi I / O (di solito, vedere di seguito).
  2. La valutazione del risultato non causa alcun effetto collaterale o output osservabile semanticamente , come la mutazione di oggetti mutabili o l'output su dispositivi I / O.

Avere variabili globali viola almeno una delle precedenti se non entrambe, poiché un codice esterno può probabilmente causare risultati imprevisti.

Un'altra chiara definizione di funzioni pure: "La funzione pura è una funzione che prende tutti i suoi input come argomenti espliciti e produce tutti i suoi output come risultati espliciti ". [1] . Avere variabili globali viola l'idea di funzioni pure poiché un input e forse uno degli output (la variabile globale) non viene esplicitamente fornito o restituito.

(Probabilmente) Violazione del PRIMO principio del test unitario

Più avanti che, se si considera unit test e il primo principio ( F test AST, I test ndependent, R epeatable, S elfo-Verifica e T imely) probabilmente saranno violare il principio di test indipendente (il che significa che i test non dipendono l'uno sull'altro).

Avere una variabile globale (non sempre) ma nella maggior parte dei casi (almeno di quello che ho visto finora) è preparare e passare i risultati ad altre funzioni. Ciò viola anche questo principio. Se la variabile globale è stata usata in quel modo (cioè la variabile globale usata nella funzione X deve essere prima impostata in una funzione Y) significa che per unit test della funzione X devi prima eseguire test / eseguire la funzione Y prima.

Globali come costanti

D'altra parte e come altre persone hanno già detto, se la variabile globale viene utilizzata come variabile "costante" può essere leggermente migliore poiché il linguaggio non supporta le costanti. Tuttavia, preferisco sempre lavorare con le classi e avere le "costanti" come membro della classe e non utilizzare affatto una variabile globale. Se si dispone di un codice che due classi diverse richiedono per condividere una variabile globale, è probabile che sia necessario rifattorizzare la soluzione e rendere le classi indipendenti.

Non credo che le globali non dovrebbero essere usate. Ma se vengono utilizzati, gli autori dovrebbero considerare alcuni principi (quelli menzionati sopra forse e altri principi e buone pratiche di ingegneria del software) per un codice più pulito e quasi privo di bug.


1
Mi piacciono le "globali come costanti sono un problema" ... perché se stai progettando OO ... lo è davvero. Perché qualcuno, tranne la classe IdCreator, deve conoscere ID_LEN?
Erik Aronesty

3

Sono essenziali, lo schermo è un buon esempio. Tuttavia, in un ambiente multithread o con molti sviluppatori coinvolti, in pratica spesso sorge la domanda: chi lo ha (erroneamente) impostato o cancellato? A seconda dell'architettura, l'analisi può essere costosa ed essere richiesta spesso. Mentre leggere la var globale può essere ok, la scrittura su di essa deve essere controllata, ad esempio da un singolo thread o da una classe threadsafe. Quindi, le variabili globali fanno sorgere il timore degli alti costi di sviluppo possibili dalle conseguenze per le quali sono considerati negativi. Pertanto, in generale, è buona norma mantenere basso il numero di variabili globali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.