2013-01-10 14 views
28

Sto utilizzando urllib.urlencode per creare parametri POST Web, tuttavia ci sono alcuni valori che voglio aggiungere solo se esiste un valore diverso da None.Aggiunta a una dict solo se viene soddisfatta una condizione

apple = 'green' 
orange = 'orange' 
params = urllib.urlencode({ 
    'apple': apple, 
    'orange': orange 
}) 

Che funziona bene, se faccio la orange variabile facoltativa, come posso impedire che venga aggiunto ai parametri? Qualcosa di simile (pseudocodice):

apple = 'green' 
orange = None 
params = urllib.urlencode({ 
    'apple': apple, 
    if orange: 'orange': orange 
}) 

Spero che questo sia stato abbastanza chiaro, qualcuno sa come risolvere questo?

+0

Se esiste un valore predefinito accettabile, è possibile utilizzare la sintassi ''orange': arancione se arancione else default'. – jpm

risposta

29

Dovrete aggiungere la chiave a parte, dopo la creazione del primo dict:

params = {'apple': apple} 
if orange is not None: 
    params['orange'] = orange 
params = urllib.urlencode(params) 

Python non ha alcuna sintassi per definire una chiave come condizionale; potresti usare una comprensione del ditt se hai già tutto in sequenza:

ma questo non è molto leggibile.

+1

Minore: questo si comporta in modo un po 'diverso se ci potrebbero essere valori diversi da Nessuno che sono falsi, come 0. – DSM

+0

@DSM: L'OP stava usando 'se arancione:' come esempio, quindi ho basato questo su quello. Leggendo più da vicino, vedo che effettivamente 'non è None' è richiesto. Ho aggiornato la risposta. –

3

È possibile cancellare Nessuno dopo la cessione:

apple = 'green' 
orange = None 
dictparams = { 
    'apple': apple, 
    'orange': orange 
} 
for k in dictparams.keys(): 
    if not dictparams[k]: 
     del dictparams[k] 
params = urllib.urlencode(dictparams) 
+1

in modo equivalente, 'd = {k: v per k, v in d.items() if v}' –

+4

Questo cancellerà anche i valori valutati su False. Si dovrebbe fare "se dictparams [k] è None" invece. – PhilipGarnero

0
fruits = [("apple", get_apple()), ("orange", get_orange()), ...] 

params = urllib.urlencode({ fruit: val for fruit, val in fruits if val is not None }) 
1

Un'altra risposta valida è che è possibile creare i propri dict-come contenitore che non memorizza i valori Nessuno.

class MyDict: 
    def __init__(self): 
     self.container = {} 
    def __getitem__(self, key): 
     return self.container[key] 
    def __setitem__(self, key, value): 
     if value != None: 
      self.container[key] = value 
    def __repr__(self): 
     return self.container.__repr__() 

a = MyDict() 
a['orange'] = 'orange'; 
a['lemon'] = None 

print a 

rendimenti:

{'orange': 'orange'} 
16

di spalle sulla risposta di sqreept, ecco una sottoclasse di dict che si comporta come desiderato:

class DictNoNone(dict): 
    def __setitem__(self, key, value): 
     if key in self or value is not None: 
      dict.__setitem__(self, key, value) 


d = DictNoNone() 
d["foo"] = None 
assert "foo" not in d 

Ciò consente valori di chiavi attuali per essere cambiato a None, ma assegnando None a una chiave che non esiste è un no-op. Se si voleva impostare un elemento da None-rimuoverlo dal dizionario se esiste già, si potrebbe fare questo:

def __setitem__(self, key, value): 
    if value is None: 
     if key in self: 
      del self[key] 
    else: 
     dict.__setitem__(self, key, value) 

Valori di Nonepuò entrare in se li passano durante la costruzione. Se si vuole evitare che, aggiungere un metodo __init__ per filtrare fuori:

def __init__(self, iterable=(), **kwargs): 
    for k, v in iterable: 
     if v is not None: self[k] = v 
    for k, v in kwargs.iteritems(): 
     if v is not None: self[k] = v 

Si potrebbe anche rendere più generica scrivendo in modo da poter passaggio nell'area condizione desiderata durante la creazione del dizionario:

class DictConditional(dict): 
    def __init__(self, cond=lambda x: x is not None): 
     self.cond = cond 
    def __setitem__(self, key, value): 
     if key in self or self.cond(value): 
      dict.__setitem__(self, key, value) 

d = DictConditional(lambda x: x != 0) 
d["foo"] = 0 # should not create key 
assert "foo" not in d 
+0

Ancora un buon esempio :) – sqreept

+0

Come si può fare questo handle d.update (foo = None)? –

+0

Scrivi un nuovo metodo '.update'. – kindall

9

Una domanda piuttosto vecchia ma qui è un'alternativa che utilizza il fatto che l'aggiornamento di un dettato con una parola vuota non fa nulla.

def urlencode_func(apple, orange=None): 
    kwargs = locals().items() 
    params = dict() 
    for key, value in kwargs: 
     params.update({} if value is None else {key: value}) 
    return urllib.urlencode(params) 
+0

Oh, molto pulito. Mi piace questa risposta la migliore! – RCross

Problemi correlati