2011-12-06 19 views
13

A causa delle regole di scoping di Python, tutte le variabili una volta inizializzate in un ambito sono disponibili successivamente. Poiché i condizionali non introducono un nuovo ambito, i costrutti in altri linguaggi (come l'inizializzazione di una variabile prima di tale condizione) non sono necessariamente necessari. Per esempio, potremmo avere:Qual è il modo pitone di inizializzazione della variabile condizionale?

def foo(optionalvar = None): 
    # some processing, resulting in... 
    message = get_message() 
    if optionalvar is not None: 
     # some other processing, resulting in... 
     message = get_other_message() 
    # ... rest of function that uses message 

o, potremmo avere invece:

def foo(optionalvar = None): 
    if optionalvar is None: 
     # processing, resulting in... 
     message = get_message() 
    else: 
     # other processing, resulting in... 
     message = get_other_message() 
    # ... rest of function that uses message 

Naturalmente, i get_message e get_other_message funzioni potrebbero essere molte righe di codice e sono sostanzialmente irrilevante (si può assumere che lo stato del programma dopo ogni percorso è lo stesso); l'obiettivo qui è rendere message pronto per l'uso oltre questa sezione della funzione.

Ho visto il secondo costrutto utilizzato più volte in altre questioni, come ad esempio:

Quale costrutto sarebbe più accettabile?

+1

Questo non dipende interamente dal fatto che si desideri 'get_message' per funzionare in modo condizionale o incondizionato? – delnan

+0

L'idea qui non è la funzione da chiamare, ma piuttosto la costruzione di 'message': la funzione stessa è irrilevante. –

+1

Sia che si tratti di una funzione o meno, l'unica differenza semantica è che si esegue la metà del codice incondizionatamente. Se fa la differenza, non ha molto senso discutere di stile. – delnan

risposta

12

Python ha anche una molto utile se modello sintassi che è possibile utilizzare qui

message = get_other_message() if optional_var else get_message() 

Oppure, se si vuole confrontare rigorosamente Nessuno

message = get_other_message() if optional_var is not None else get_message() 

differenza con l'esempio 1) hai postato questo doesn chiamiamo get_message() inutilmente.

+1

Questo è ** IL ** modo Pythonic per eseguire assegnazioni condizionali (dalla v2.5), almeno per quanto riguarda la lingua stessa. Dai un'occhiata a [PEP 308] (http://docs.python.org/release/2.5/whatsnew/pep-308.html) per maggiori informazioni. – voithos

+0

Sembra inoltre che PEP 308 suggerisca che il secondo formato fosse il precedente modo accettabile per farlo. Buono a sapersi! –

1

Penso che sia più sdolcinato non impostare una regola esplicita su questo, e invece basti pensare che funzioni piccole sono migliori (in parte perché è possibile tenere a mente proprio quando vengono introdotti nuovi nomi).

Suppongo però che se i test condizionali ottenere molto più complicato di un if/else si può correre il rischio di tutti loro in mancanza e in seguito utilizzando un nome definito, con conseguente possibilità di errore di runtime, a meno che non siete molto attenti. Questo potrebbe essere un argomento per il primo stile, quando è possibile.

0

La risposta dipende da se ci sono effetti collaterali di get_message() che si vogliono.

Nella maggior parte dei casi in modo chiaro la seconda vince, perché il codice che produce il risultato indesiderato non viene eseguito. Ma se hai bisogno degli effetti collaterali, dovresti scegliere la prima versione.

0

Potrebbe essere meglio (leggi: più sicuro) per inizializzare la variabile di fuori delle condizioni. Se è necessario definire altre condizioni o addirittura rimuoverne alcune, in seguito l'utente di message potrebbe ricevere un'eccezione variabile non inizializzata.

4

Al secondo approccio generale è migliore e più generico in quanto non comporta chiamando get_message incondizionatamente.Che può essere ok se tale funzione non è di risorse incentivo ma si consideri una funzione di ricerca

def search(engine): 
    results = get_from_google() 
    if engine == 'bing': 
     results = get_from_bing() 

, ovviamente, questo non è buono, non riesco a pensare a tale scenario male per secondo caso, in modo sostanzialmente un approccio che passa attraverso tutti opzioni e, infine, l'impostazione predefinita è meglio eg

def search(engine): 
    if engine == 'bing': 
     results = get_from_bing() 
    else: 
     results = get_from_google() 
Problemi correlati