2009-11-02 4 views
38

Provengo da uno sfondo PHP e vorrei sapere se c'è un modo per farlo in Python.Come evitare di scrivere request.GET.get() due volte per stamparlo?

In PHP si può uccidere 2 piccioni con una fava come questo:

Invece di:

if(getData()){ 
    $data = getData(); 
    echo $data; 
} 

posso fare questo:

if($data = getData()){ 
    echo $data; 
} 

di controllare per vedere se getData() esiste E se lo fa, lo assegni a una variabile in una dichiarazione.

Volevo sapere se c'è un modo per farlo in Python? Così, invece di fare questo:

if request.GET.get('q'): 
    q = request.GET.get('q') 
    print q 

evitare di scrivere request.GET.get('q') due volte.

+0

Avete un tutorial Python con segnalibro? Quale? –

+1

Proprio quello ufficiale: http://docs.python.org/tutorial/ – givp

+2

Fortunatamente, Python non ha questa disfunzione di C, e in generale, nella maggior parte dei linguaggi che lo hanno ereditato da C/C++, il suo uso è disapprovato per motivi di leggibilità e chiarezza. –

risposta

25

Probabilmente non è esattamente quello che stavi pensando, ma ...

q = request.GET.get('q') 
if q: 
    print q 

questo?

+0

sì, è vero. il modello consiste nell'utilizzare una variabile se e solo se esiste (nel senso che fornisce un valore valido, ad esempio qualsiasi cosa tranne * False *). –

+0

Grazie, sembra che questo sia il modo migliore per farlo. Come dice @Adam, non è possibile farlo in Python. Grazie. – givp

+7

La limitazione di questa soluzione è se si desidera utilizzarla in una serie di if-elif-elif-elif ecc. Ad esempio, vedere questa altra domanda SO: http://stackoverflow.com/questions/122277/how-do -you-translate-this-espressione-regolare-idioma-da-perl-in-python –

24

Vedere la mia ricetta di 8 anni here proprio per questa attività.

# In Python, you can't code "if x=foo():" -- assignment is a statement, thus 
# you can't fit it into an expression, as needed for conditions of if and 
# while statements, &c. No problem, if you just structure your code around 
# this. But sometimes you're transliterating C, or Perl, or ..., and you'd 
# like your transliteration to be structurally close to the original. 
# 
# No problem, again! One tiny, simple utility class makes it easy...: 

class DataHolder: 
    def __init__(self, value=None): self.value = value 
    def set(self, value): self.value = value; return value 
    def get(self): return self.value 
# optional but handy, if you use this a lot, either or both of: 
setattr(__builtins__,'DataHolder',DataHolder) 
setattr(__builtins__,'data',DataHolder()) 

# and now, assign-and-set to your heart's content: rather than Pythonic 
while 1: 
    line = file.readline() 
    if not line: break 
    process(line) 
# or better in modern Python, but quite far from C-like idioms: 
for line in file.xreadlines(): 
    process(line) 
# you CAN have your C-like code-structure intact in transliteration: 
while data.set(file.readline()): 
    process(data.get()) 
+29

Hai un bambino di 8 anni piuttosto intelligente! ;) – unutbu

+2

@unutbu, heh - questo sarebbe il mio (vecchio) gatto come i miei figli sono un po 'più grandi ... la mia figlia minore ha appena iniziato il dottorato in ingegneria delle telecomunicazioni (sistemi radio avanzati, soprattutto) ... ;-) –

0

Beh, questo sarebbe un modo

q = request.GET.get('q') 
if q: 
    print q 

A più breve (ma non superiore, a causa della chiamata alla stampa di niente) modo sarebbe

print request.GET.get('q') or '', 
2
q = request.GET.get('q') 
if q: 
    print q 
else: 
    # q is None 
    ... 

Non c'è modo di fare incarichi e condizionali in una volta ...

+0

L'esplicito è meglio che implicito. Conta la leggibilità I casi speciali non sono abbastanza speciali da infrangere le regole. Stai salvando così tanto spazio verticale nel tuo codice non scrivendo tutte quelle linee con nient'altro che una parentesi graffa, quindi perché non fare chiarezza in Python? Personalmente, ho tagliato i denti su C e ho scritto codice Python per 12 anni, e non mi ero mai reso conto che mancasse questa funzionalità. Non hai proprio bisogno di farlo. –

+0

@ Michael: sono d'accordo in quasi tutti i casi. Mi manca solo nel caso di utilizzo specifico di test di più espressioni regolari, come descritto in questa altra domanda SO: http://stackoverflow.com/questions/122277/how-do-you-translate-this-regular-expression- idiom-from-perl-in-python –

2

Se get() genera un'eccezione quando non c'è, si potrebbe fare

try: 
    q = request.GET.get('q') 
    print q 
except : 
    pass 
9

Una variazione sul Alex's answer:

class DataHolder: 
    def __init__(self, value=None, attr_name='value'): 
     self._attr_name = attr_name 
     self.set(value) 
    def __call__(self, value): 
     return self.set(value) 
    def set(self, value): 
     setattr(self, self._attr_name, value) 
     return value 
    def get(self): 
     return getattr(self, self._attr_name) 
save_data = DataHolder() 

Usage:

if save_data(get_input()): 
    print save_data.value 

o se si preferisce un interfaccia alternativa:

if save_data.set(get_input()): 
    print save_data.get() 

avrei trovato questa utile per testare una serie di espressioni regolari in un se-elif-elif-elif ecc costrutto, come in this SO question:

import re 

input = u'test bar 123' 
save_match = DataHolder(attr_name='match') 
if save_match(re.search('foo (\d+)', input)): 
    print "Foo" 
    print save_match.match.group(1) 
elif save_match(re.search('bar (\d+)', input)): 
    print "Bar" 
    print save_match.match.group(1) 
elif save_match(re.search('baz (\d+)', input)): 
    print "Baz" 
    print save_match.match.group(1) 
+0

Mi piace l'aggiunta di '__call __()' a DataHolder, ma non capisco perché sia ​​utile specificare 'attr_name'. Se DataHolder fosse un singleton o se un'istanza di esso potesse contenere più valori, ciascuno in attributi diversi, lo capisco, ma non sembra avere uno scopo forte qui. –

+1

@LS: Sì, avrei potuto semplicemente corretto "valore" o "x".Ma [buoni nomi variabili] (http://c2.com/cgi/wiki?GoodVariableNames) migliorano la leggibilità. Questa è l'essenza di ciò. –

0
config_hash = {} 
tmp_dir = ([config_hash[x] for x in ["tmp_dir"] if config_hash.has_key(x)] or ["tmp"])[0] 
print tmp_dir 
config_hash["tmp_dir"] = "cat" 
tmp_dir = ([config_hash[x] for x in ["tmp_dir"] if config_hash.has_key(x)] or ["tmp"])[0] 
print tmp_dir 
0

un possibile modo per farlo, senza necessità di impostare la variabile prima, potrebbe essere:

if (lambda x: globals().update({'q':x}) or True if x else False)(request.GET.get('q')): 
    print q 

..è solo per divertimento - questo metodo non dovrebbe essere usato, perché è brutto hack, difficile da capire a prima vista, e crea/sovrascrive una variabile globale (solo se la condizione è soddisfatta, però)

0

Basta provare:

print(request.GET.get('q', '')) 

che stampa praticamente nulla se il primo argomento non è presente (vedi dict.get).


soluzione alternativa sarebbe quella di utilizzare un'espressione condizionale in Python:

<expression1> if <condition> else <expression2> 

ma si finirà per ripetere variabile due volte, ad esempio:

print(request.GET.get('q') if request.GET.get('q') else '') 

Per assegnazioni variabili in loop, check in here.