Ich verwende urllib.urlencode
zum Erstellen von Web-POST-Parametern, es gibt jedoch einige Werte, die nur hinzugefügt werden sollen, wenn ein anderer Wert als None
der für sie vorhanden ist.
apple = 'green'
orange = 'orange'
params = urllib.urlencode({
'apple': apple,
'orange': orange
})
Das funktioniert gut, aber wenn ich die orange
Variable optional mache , wie kann ich verhindern, dass sie zu den Parametern hinzugefügt wird? So etwas (Pseudocode):
apple = 'green'
orange = None
params = urllib.urlencode({
'apple': apple,
if orange: 'orange': orange
})
Ich hoffe das war klar genug, weiß jemand wie man das löst?
python
variables
dictionary
urllib
user1814016
quelle
quelle
'orange': orange if orange else default
Syntax verwenden.Antworten:
Sie müssen den Schlüssel nach dem Erstellen der Initiale separat hinzufügen
dict
:params = {'apple': apple} if orange is not None: params['orange'] = orange params = urllib.urlencode(params)
Python hat keine Syntax, um einen Schlüssel als bedingt zu definieren. Sie könnten ein Diktatverständnis verwenden, wenn Sie bereits alles in einer Sequenz hätten:
params = urllib.urlencode({k: v for k, v in (('orange', orange), ('apple', apple)) if v is not None})
aber das ist nicht sehr lesbar.
Eine andere Möglichkeit ist das Entpacken des Wörterbuchs , aber für einen einzelnen Schlüssel ist das nicht viel besser lesbar:
params = urllib.urlencode({ 'apple': apple, **({'orange': orange} if orange is not None else {}) })
Ich persönlich würde dies niemals verwenden, es ist zu hackig und bei weitem nicht so explizit und klar wie die Verwendung einer separaten
if
Aussage. Wie das Zen von Python sagt: Lesbarkeit zählt.quelle
**({key: value} if test else {})
wirklich nicht besser lesbar.{key: value}
einem verschachtelten Diktat Paare hinzuzufügen , bei denen sowohl Schlüssel als auch Wert von anderen Schlüsseln und Werten abgeleitet (zusammengesetzt) wurden. Diesif something: ...
würde in meinem Fall definitiv die Lesbarkeit beeinträchtigen (aufgrund der Verschachtelung, die dann zweimal oder öfter angewendet werden müsste). YMMV hier von Fall zu Fall.Um auf die Antwort von sqreept zurückzugreifen
dict
, verhält sich eine Unterklasse davon wie gewünscht: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
Auf diese Weise kann Werte von vorhandenen Schlüsseln werden geändert zu
None
, aber die ZuordnungNone
zu einem Schlüssel, der nicht existiert ein no-op ist. Wenn Sie Einstellung ein Element wollte entfernen sie aus dem Wörterbuch , wenn es bereits vorhanden ist , können Sie dies tun:None
def __setitem__(self, key, value): if value is None: if key in self: del self[key] else: dict.__setitem__(self, key, value)
Werte von
None
können eintreten, wenn Sie sie während des Baus weitergeben. Wenn Sie dies vermeiden möchten, fügen Sie eine__init__
Methode hinzu, um sie herauszufiltern: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
Man könnte es auch generische machen , indem es zu schreiben , so dass Sie kann in passiert den gewünschten Zustand , wenn das Wörterbuch zu erstellen:
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
quelle
__class__
diktieren, anstatt isinstance-Prüfungen zu bestehen). Es ist möglich, dass dies in diesem Fall nicht zutrifft (ich habe die Umkehrung durchgeführt und Schlüssel und Werte beim Extrahieren und nicht bei der Eingabe transformiert), aber ich hinterlasse diesen Kommentar nur für den Fall, dass es hilfreich istparams = urllib.urlencode({ 'apple': apple, **({'orange': orange} if orange else {}), })
quelle
Ziemlich alte Frage, aber hier ist eine Alternative, die die Tatsache nutzt, dass das Aktualisieren eines Diktats mit einem leeren Diktat nichts bewirkt.
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)
quelle
params.update({key: val for key, val in kwargs if val is not None})
Ich tat dies. Ich hoffe das hilft.
apple = 23 orange = 10 a = { 'apple' : apple, 'orange' if orange else None : orange }
Erwartete Ausgabe :
{'orange': 10, 'apple': 23}
Wenn ja
orange = None
, dann gibt es einen einzigen Eintrag fürNone:None
. Betrachten Sie zum Beispiel Folgendes:apple = 23 orange = None a = { 'apple' : apple, 'orange' if orange else None : orange }
Erwartete Ausgabe :
{None: None, 'apple': 23}
quelle
None
. Ich würde vorschlagen, nur die Bedingung für den Schlüssel auszuführen (wenn Sie sich Sorgen machen, dass der Wert vorhanden ist, fügen Sie ihn einfachNone: None
als letzte Zeile in der Diktatdeklaration hinzu) und anschließenddel a[None]
.a.pop(None)
und es ist perfektSie können Keine nach der Zuweisung löschen:
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)
quelle
d = {k:v for k,v in d.items() if v}
if dictparams[k] is None
stattdessen tun .d = {k:v for k,v in d.items() if v is not None}
, dannEine andere gültige Antwort ist, dass Sie einen eigenen diktartigen Container erstellen können, in dem keine None-Werte gespeichert sind.
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
Ausbeuten:
{'orange': 'orange'}
quelle
Ich mag den tollen Trick in der Antwort hier wirklich: https://stackoverflow.com/a/50311983/3124256
Aber es hat einige Fallstricke:
if
Tests (wiederholt für Schlüssel und Wert)None: None
Eintrag im Ergebnisdict
Um dies zu vermeiden, können Sie Folgendes tun:
apple = 23 orange = None banana = None a = { 'apple' if apple else None: apple, 'orange' if orange else None : orange, 'banana' if banana else None: banana, None: None, } del a[None]
Erwartete Ausgabe :
{'apple': 23}
Hinweis: Der
None: None
Eintrag stellt zwei Dinge sicher:None
Schlüssel ist immer vorhanden (del
wirft keinen Fehler)del
später vergessen )Wenn Sie sich über diese Dinge keine Sorgen machen, können Sie sie weglassen und das Del in ein einwickeln
try...except
(oder prüfen, ob derNone
Schlüssel vorhanden ist, bevor Siedel
loslegen). Um alternativ Nummer 2 zu adressieren, können Sie den Wert auch zusätzlich zum Schlüssel bedingt prüfen.quelle
fruits = [("apple", get_apple()), ("orange", get_orange()), ...] params = urllib.urlencode({ fruit: val for fruit, val in fruits if val is not None })
quelle
getter
für jede Variable. Warum nicht einfach tun:fruits={"apple", "orange"}; d=vars(); params = urllib.urlencode({ fruit: val for fruit, val in d.items() if fruit in fruits and val is not None })
Es gibt einen kontraintuitiven, aber zuverlässigen Hack, um den anderen Requisitennamen, den Sie ausschließen möchten, wiederzuverwenden.
{ 'orange' if orange else 'apple': orange, 'apple': apple, }
In diesem Fall überschreibt der letztere "Apfel" den vorherigen "Apfel" und entfernt ihn effektiv. Beachten Sie, dass die bedingten Ausdrücke über die realen hinausgehen sollten.
quelle