Подтвердить что ты не робот

Добавляйте только к dict, если выполняется условие

Я использую urllib.urlencode для создания параметров веб-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
})

Надеюсь, это было достаточно ясно, кто-нибудь знает, как это решить?

4b9b3361

Ответ 1

Вам нужно будет добавить ключ отдельно, после создания начального 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})

но это не очень читаемо.

Ответ 2

Чтобы получить ответ на 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 к ключу, который не существует, является 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)

Значения 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

Вы также можете сделать его общим, написав его, чтобы при создании словаря вы могли перейти в желаемое условие:

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

Ответ 3

Довольно старый вопрос, но вот альтернатива, использующая тот факт, что обновление 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)

Ответ 4

Вы можете очистить 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)

Ответ 5

Еще один правильный ответ заключается в том, что вы можете создать свой собственный диктоподобный контейнер, который не сохраняет значения 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

дает:

{'orange': 'orange'}

Ответ 6

Я сделал это. Надеюсь, это поможет.

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. Например, рассмотрим это:

apple = 23
orange = None
a = {
    'apple' : apple,
    'orange' if orange else None : orange if orange else None
}

Ожидаемый результат: {None: None, 'apple': 23}

Ответ 7

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

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