Python 仅在满足条件时才添加到 dict
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14263872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Only add to a dict if a condition is met
提问by user1814016
I am using urllib.urlencodeto build web POST parameters, however there are a few values I only want to be added if a value other than Noneexists for them.
我正在使用urllib.urlencode构建 web POST 参数,但是有一些值我只想添加,如果None它们不存在其他值。
apple = 'green'
orange = 'orange'
params = urllib.urlencode({
'apple': apple,
'orange': orange
})
That works fine, however if I make the orangevariable optional, how can I prevent it from being added to the parameters? Something like this (pseudocode):
这工作正常,但是如果我将orange变量设为可选,如何防止它被添加到参数中?像这样(伪代码):
apple = 'green'
orange = None
params = urllib.urlencode({
'apple': apple,
if orange: 'orange': orange
})
I hope this was clear enough, does anyone know how to solve this?
我希望这已经足够清楚了,有谁知道如何解决这个问题?
采纳答案by Martijn Pieters
You'll have to add the key separately, after the creating the initial dict:
在创建初始后,您必须单独添加密钥dict:
params = {'apple': apple}
if orange is not None:
params['orange'] = orange
params = urllib.urlencode(params)
Python has no syntax to define a key as conditional; you could use a dict comprehension if you already had everything in a sequence:
Python 没有将键定义为条件的语法;如果您已经将所有内容按顺序排列,则可以使用 dict 理解:
params = urllib.urlencode({k: v for k, v in (('orange', orange), ('apple', apple)) if v is not None})
but that's not very readable.
但这不是很可读。
Another option is to use dictionary unpacking, but for a single key that's not all that more readable:
另一种选择是使用字典 unpacking,但对于单个键,并不是那么可读:
params = urllib.urlencode({
'apple': apple,
**({'orange': orange} if orange is not None else {})
})
I personally would never use this, it's too hacky and is not nearly as explicit and clearas using a separate ifstatement. As the Zen of Pythonstates: Readability counts.
回答by sqreept
You can clear None after the assignment:
您可以在分配后清除 None :
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)
回答by XORcist
fruits = [("apple", get_apple()), ("orange", get_orange()), ...]
params = urllib.urlencode({ fruit: val for fruit, val in fruits if val is not None })
回答by sqreept
Another valid answer is that you can create you own dict-like container that doesn't store None values.
另一个有效的答案是,您可以创建自己的类似 dict 的容器,该容器不存储 None 值。
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
yields:
产量:
{'orange': 'orange'}
回答by kindall
To piggyback on sqreept's answer, here's a subclass of dictthat behaves as desired:
要搭载 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
This will allow values of existing keys to be changedto None, but assigning Noneto a key that does not exist is a no-op. If you wanted setting an item to Noneto removeit from the dictionary if it already exists, you could do this:
这将允许将现有键的值更改为None,但分配None给不存在的键是无操作的。如果你想设置的项目None,以除去从如果它已经存在的字典,你可以这样做:
def __setitem__(self, key, value):
if value is None:
if key in self:
del self[key]
else:
dict.__setitem__(self, key, value)
Values of Nonecanget in if you pass them in during construction. If you want to avoid that, add an __init__method to filter them out:
值None可以,如果你在施工过程中通过他们进去。如果您想避免这种情况,请添加一个__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
You could also make it generic by writing it so you can pass inthe desired condition when creating the dictionary:
您还可以通过编写它来使其通用,以便在创建字典时传递所需的条件:
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
回答by lindsay.stevens.au
Pretty old question but here is an alternative using the fact that updating a dict with an empty dict does nothing.
很老的问题,但这里有一个替代方案,即使用空 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)
回答by Nikhil Wagh
I did this. Hope this help.
我这样做了。希望这有帮助。
apple = 23
orange = 10
a = {
'apple' : apple,
'orange' if orange else None : orange
}
Expected output : {'orange': 10, 'apple': 23}
预期输出: {'orange': 10, 'apple': 23}
Although, if orange = None, then there will be a single entry for None:None. For example consider this :
虽然,如果orange = None,那么 将有一个条目None:None。例如考虑这个:
apple = 23
orange = None
a = {
'apple' : apple,
'orange' if orange else None : orange
}
Expected Output : {None: None, 'apple': 23}
预期输出: {None: None, 'apple': 23}
回答by DylanYoung
I really like the neat trick in the answer here: https://stackoverflow.com/a/50311983/3124256
我真的很喜欢这里答案中的巧妙技巧:https: //stackoverflow.com/a/50311983/3124256
But, it has some pitfalls:
但是,它有一些陷阱:
- Duplicate
iftests (repeated for key and value) - Pesky
None: Noneentry in the resultingdict
- 重复
if测试(对键和值重复) - 结果中的讨厌
None: None条目dict
To avoid this, you can do the following:
为避免这种情况,您可以执行以下操作:
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]
Expected Output : {'apple': 23}
预期输出: {'apple': 23}
Note: the None: Noneentry ensures two things:
注意:该None: None条目确保两件事:
- The
Nonekey will always be present (delwon't throw an error) - The contents of 'None values' will never exist in the dict (in case you forget to
delafterwards)
- 该
None键将始终存在(del会不会引发错误) - 字典中永远不会存在“无值”的内容(以防您
del之后忘记)
If you aren't worried about these things, you can leave it out and wrap the del in a try...except(or check if the Nonekey is present before deling). To address number 2 alternatively, you could also put the conditional check on the value (in addition to the key).
如果您不担心这些事情,您可以将其省略并将 del 包裹在 a 中try...except(或None在deling之前检查密钥是否存在)。或者,要解决数字 2,您还可以对值进行条件检查(除了键之外)。
回答by Данила Фомин
params = urllib.urlencode({
'apple': apple,
**({'orange': orange} if orange else {}),
})
回答by Ilya Kharlamov
There is a counter-intuitive but reliable hack, to reuse the other prop name you want to exclude it.
有一个违反直觉但可靠的技巧,可以重用您想要排除的其他道具名称。
{
'orange' if orange else 'apple': orange,
'apple': apple,
}
In this case, the latter 'apple' will override the previous 'apple' effectively removing it. Note that the conditional expressions should go above the real ones.
在这种情况下,后一个“苹果”将覆盖前一个“苹果”,有效地将其删除。请注意,条件表达式应高于真实表达式。

