使っています urllib.urlencode
を使用してWeb POSTパラメーターを作成しますが、None
以外の値が存在する場合にのみ追加したい値がいくつかあります。
Apple = 'green'
orange = 'orange'
params = urllib.urlencode({
'Apple': Apple,
'orange': orange
})
それはうまくいきますが、orange
変数をオプションにした場合、パラメーターに追加されないようにするにはどうすればよいですか?次のようなもの(擬似コード):
Apple = 'green'
orange = None
params = urllib.urlencode({
'Apple': Apple,
if orange: 'orange': orange
})
これが十分に明確であったことを願っていますが、誰もこれを解決する方法を知っていますか?
最初のdict
を作成した後、キーを個別に追加する必要があります。
params = {'Apple': Apple}
if orange is not None:
params['orange'] = orange
params = urllib.urlencode(params)
Pythonには、キーを条件付きとして定義する構文がありません。シーケンス内のすべてがすでにある場合は、dict内包表記を使用できます。
params = urllib.urlencode({k: v for k, v in (('orange', orange), ('Apple', Apple)) if v is not None})
しかし、それはあまり読めません。
Sqreeptの答えに便乗するために、以下のdict
のサブクラスが必要に応じて動作します。
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
これにより、既存のキーの値を変更からNone
にできますが、None
を存在しないキーに割り当てることは何もしません。アイテムをNone
にremoveに設定したい場合、既に存在する場合は辞書から、これを行うことができます:
def __setitem__(self, key, value):
if value is None:
if key in self:
del self[key]
else:
dict.__setitem__(self, key, value)
None
canの値は、構築中に渡すと取得されます。それを避けたい場合は、__init__
それらを除外するメソッド:
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
また、辞書を作成するときに、pass in目的の条件を作成できるように記述することで、汎用にすることもできます。
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
かなり古い質問ですが、空のdictでdictを更新しても何も起こらないという事実を使用した代替案です。
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)
params = urllib.urlencode({
'Apple': Apple,
**({'orange': orange} if orange else {}),
})
割り当て後に[なし]をクリアできます。
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)
これは私がしました。この助けを願っています。
Apple = 23
orange = 10
a = {
'Apple' : Apple,
'orange' if orange else None : orange if orange else None
}
期待される出力:{'orange': 10, 'Apple': 23}
ただし、orange = None
の場合、None:None
のエントリは1つになります。たとえば、これを考慮してください:
Apple = 23
orange = None
a = {
'Apple' : Apple,
'orange' if orange else None : orange if orange else None
}
期待される出力:{None: None, 'Apple': 23}
別の有効な答えは、None値を格納しない独自のdictのようなコンテナを作成できるということです。
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
収量:
{'orange': 'orange'}
私はここの答えのきちんとしたトリックが本当に好きです: https://stackoverflow.com/a/50311983/3124256
しかし、いくつかの落とし穴があります。
if
テストの重複(キーと値について繰り返される)dict
の厄介なNone: None
エントリこれを回避するには、次のことを実行できます。
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]
期待される出力:{'Apple': 23}
注:None: None
エントリは、次の2つのことを保証します。
None
キーは常に存在します(del
はエラーをスローしません)del
を忘れた場合)これらのことを心配しない場合は、それを省いてtry...except
で囲むことができます(またはNone
ingの前にdel
キーが存在するかどうかを確認します)。代わりに番号2に対処するには、(キーに加えて)値の条件付きチェックを行うこともできます。
fruits = [("Apple", get_Apple()), ("orange", get_orange()), ...]
params = urllib.urlencode({ fruit: val for fruit, val in fruits if val is not None })