只有在满足条件时才添加到dict

use*_*016 57 python variables dictionary urllib

我正在使用urllib.urlencode构建Web POST参数,但是如果存在除了它们之外的值,我只想添加一些值None.

apple = 'green'
orange = 'orange'
params = urllib.urlencode({
    'apple': apple,
    'orange': orange
})
Run Code Online (Sandbox Code Playgroud)

这工作正常,但是如果我将orange变量设为可选,我怎样才能防止它被添加到参数中?像这样的东西(伪代码):

apple = 'green'
orange = None
params = urllib.urlencode({
    'apple': apple,
    if orange: 'orange': orange
})
Run Code Online (Sandbox Code Playgroud)

我希望这很清楚,有谁知道如何解决这个问题?

Mar*_*ers 47

在创建初始化之后,您必须单独添加密钥dict:

params = {'apple': apple}
if orange is not None:
    params['orange'] = orange
params = urllib.urlencode(params)
Run Code Online (Sandbox Code Playgroud)

Python没有将键定义为条件的语法; 如果你已经拥有了序列中的所有内容,你可以使用dict理解:

params = urllib.urlencode({k: v for k, v in (('orange', orange), ('apple', apple)) if v is not None})
Run Code Online (Sandbox Code Playgroud)

但那不是很可读.

  • 对于 Python 3.5 及更高版本:自 [PEP-0448](https://www.python.org/dev/peps/pep-0448/) 实施以来(建议于 2013 年 6 月 29 日),https://stackoverflow.com /a/55341342/563970 应该是答案 (2认同)

kin*_*all 31

为了搭载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
Run Code Online (Sandbox Code Playgroud)

这将允许将现有密钥的值更改None,但是分配None给不存在的密钥是no-op.如果你想设置的项目None,以除去从如果它已经存在的字典,你可以这样做:

def __setitem__(self, key, value):
    if value is None:
        if key in self:
            del self[key]
    else:
        dict.__setitem__(self, key, value)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

您也可以通过编写它使它成为通用的,这样您就可以创建字典时传递所需的条件:

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
Run Code Online (Sandbox Code Playgroud)


kmu*_*ui2 22

我建议的一种技术是使用字典解包操作符

apple = 'green'
orange = None
params = urllib.urlencode({
    'apple': apple,
    **({ 'orange': orange } if orange else {})
})
Run Code Online (Sandbox Code Playgroud)

解释

基本上,如果orangeNone,那么上面的字典简化为

{
    'apple': apple,
    **({})
}

# which results in just
{
    'apple': apple,
} 
Run Code Online (Sandbox Code Playgroud)

orangeif is not则相反None

{
    'apple': apple,
    **({})
}

# which results in just
{
    'apple': apple,
} 
Run Code Online (Sandbox Code Playgroud)

可读性是有条件地内联添加键的一个缺点。可以创建一个可以帮助解决可读性问题的函数。

{
    'apple': apple,
    **({ "orange": orange })
}

# which results in just
{
    'apple': apple,
    'orange': orange
} 
Run Code Online (Sandbox Code Playgroud)


小智 13

相当古老的问题,但这里是一个替代使用更新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)
Run Code Online (Sandbox Code Playgroud)


小智 11

params = urllib.urlencode({
    'apple': apple,
    **({'orange': orange} if orange else {}),
})
Run Code Online (Sandbox Code Playgroud)


Nik*_*agh 5

我这样做了。希望这有帮助。

apple = 23
orange = 10
a = {
    'apple' : apple,
    'orange' if orange else None : orange
}
Run Code Online (Sandbox Code Playgroud)

预期输出: {'orange': 10, 'apple': 23}

虽然,如果orange = None,那么 将有一个条目None:None。例如考虑这个:

apple = 23
orange = None
a = {
    'apple' : apple,
    'orange' if orange else None : orange
}
Run Code Online (Sandbox Code Playgroud)

预期输出: {None: None, 'apple': 23}

  • 除此之外:**抵制使用技巧的冲动**。此代码需要附加语句(“a.pop(None)”或“if None in a: del a[None]”),并且需要在注释中为必须维护代码的未来开发人员提供解释。 (2认同)