2015-12-18 17 views
6

Stavo scrivendo una piccola utility di file in precedenza e ho riscontrato un problema con il passaggio per riferimento. Dopo aver letto How do I pass a variable by reference?, ho impostato la variabile che volevo passare come argomento e anche come valore di ritorno. Entro il codice qui sotto, è la linea:Modo Pythonic per mantenere l'assegnazione variabile

diff = compareDir(path0, path0List, path1, path1List, diff) 

dove diff è la variabile volevo passare per riferimento.

Mentre funziona, sembra piuttosto imbarazzante. Penso che ci debba essere un modo migliore. In molte altre lingue, potrei semplicemente impostare compareLists() per non avere alcun valore di ritorno e usare l'effetto collaterale della modifica dell'argomento pass-by-reference. Il pass-by-assignment di Python sembra non consentire questo.

Sono relativamente nuovo a Python e vorrei sapere se esiste un modo più pitioso per risolvere il problema. Richiederebbe ripensare completamente le funzioni? O c'è una bella affermazione di cui non sono a conoscenza? Mi piacerebbe stare lontano dalle variabili globali.

Accolgo qualsiasi critica e commento costruttivo. Grazie!

Codice Rilevante:

def comparePaths(path0, path1): 
    path0List = os.listdir(path0) 
    path1List = os.listdir(path1) 

    diff = False 
    diff = compareDir(path0, path0List, path1, path1List, diff) 
    print() 
    diff = compareDir(path1, path1List, path0, path0List, diff) 
    return diff 

def compareDir(basePath, baseList, comparePath, compareDir, diffVar): 
    for entry in baseList: 
     #compare to the other folder 
     if (not (entry in compareDir)): 
      if (not (diffVar)): 
       diffVar = True 
       print ("Discreptancies found. The following files are different:") 
       print (str(entry) + " doesn\'t exist in " + str(comparePath)) 
      else: 
       print (str(entry) + " doesn\'t exist in " + str(comparePath)) 
    return diffVar 
+1

Se si desidera ridurre i parametri a qualcosa in cui si chiama 'compareListe()', penso che potrebbe essere necessario riconsiderare il proprio approccio. Forse memorizzando i tuoi valori in un dizionario perché in questo modo puoi modificare le coppie chiave/valore ovunque nello spazio dei nomi. – Dan

+0

Grazie Dan, questo è un eccellente suggerimento. Potrei fare proprio questo. –

+0

La risposta collegata fa un ottimo lavoro di spiegazione della distinzione tra oggetti mutevoli e immutabili. 'diff = False' è immutabile. 'diff = [False]' è mutabile. – hpaulj

risposta

3

Poiché in Python, il tipo bool è per definizione immutabile, l'unico modo per modificare una variabile bool all'interno di una funzione senza riassegnandolo (e senza definire come variabile globale) è di memorizzarlo in un'istanza di tipo mutevole. es .:

  • Memorizzarlo in una struttura di dati mutabile (elenco, dict, ...) e passare questa struttura di dati alla funzione.
  • Avere come attributo di un oggetto mutabile e passare questo oggetto alla funzione.
+0

Grazie Dim. Non ti capita di avere un riferimento pydoc ai tipi mutabili vs immutabili? Ho trovato [questo riferimento sulle sequenze mutevoli e immutabili] (https://docs.python.org/3.5/reference/datamodel.html # the-standard-type-hierarchy) ma potrebbe usare più informazioni. –

+1

No, ma penso che sia tutto lì: - i tipi numerici (int, float, complesso) sono immutabili. - str, byte e tupla sono sequenze immutabili. - elenco e bytearray sono mutabili. - set è mutabile, frozenset è immutabile. - dict è mutabile. –

+0

Grazie @Dim apprezzo il tuo aiuto. –

2

Il tuo problema ha più soluzioni possibili.

È possibile aggiungere il modificatore nonlocal (global precedente a python3) affinché la variabile differenziale possa essere modificata dalla funzione interna e le modifiche siano visibili dall'esterno.

diff = False 

    def compareDir(basePath, baseList, comparePath, compareDir): 
     nonlocal diff 
     for entry in baseList: 
        ... 
        diff = True 

    compareDir(path0, path0List, path1, path1List) 
    print() 
    compareDir(path1, path1List, path0, path0List) 
    return diff 

Oppure si può avere soluzione OOP con differ oggetto e self.diff come condizione esplicita di tale oggetto.

class differ(object): 
    def __init__(self): 
     self.diff = False 
    def compareDir(self, basePath, baseList, comparePath, compareDir): 
     ... 
       self.diff = True 
     ... 

    def comparePaths(self, path0, path1): 

soluzione quest'ultimo è super disponibile, se avete bisogno di fare un sacco di lavoro in un po 'di contesto' e spesso bisogno di cambiare stato condiviso.

Problemi correlati