Python: разница между kwargs.pop() и kwargs.get()

Я видел оба пути, но я не понимаю, в чем разница и что я должен использовать в качестве "лучшей практики":

def custom_function(**kwargs):
    foo = kwargs.pop('foo')
    bar = kwargs.pop('bar')
    ...

def custom_function2(**kwargs):
    foo = kwargs.get('foo')
    bar = kwargs.get('bar')
    ...

Ответ 1

get (key [, default]): вернуть значение для ключа, если ключ находится в словаре, иначе по умолчанию. Если значение по умолчанию не задано, по умолчанию оно равно None, так что этот метод никогда не вызывает KeyError.

d = {'a' :1, 'c' :2}
print(d.get('b', 0)) # return 0
print(d.get('c', 0)) # return 2

pop (key [, default]), если ключ находится в словаре, удалите его и верните его значение, иначе верните значение по умолчанию. Если значение по умолчанию не задано, а ключ отсутствует в словаре, возникает KeyError.

d = {'a' :1, 'c' :2}
print(d.pop('c', 0)) # return 2
print(d) # returns {'a': 1}
print(d.get('c', 0)) # return 0

NB: Что касается вопроса с наилучшей практикой, я бы сказал, что это зависит от вашего .get использования, но я по умолчанию по умолчанию .get если у меня нет реальной потребности в .pop

Ответ 2

Разница pop также удаляет элемент из dict.

Нет лучшей практики. Используйте тот, который более удобен для вашего конкретного случая использования.

В большинстве случаев все, что вам нужно, это get ценность.

В других случаях вы хотите убедиться, что никаких дополнительных/неожиданных kwargs не предусмотрено. В этом случае удобно использовать pop. Например:

a = kw.pop('a')
b = kw.pop('b')
if kw:
    raise TypeError('Unepxected kwargs provided: %s' % list(kw.keys()))

Ответ 3

Таким образом, функции get и pop выполняют разные вещи

get используется для возврата значения для заданного ключа в словаре

pop удаляет значение из словаря и возвращает удаленное значение

Все функции словаря описаны здесь (для python3): https://docs.python.org/3/library/stdtypes.html#mapping-types-dict

Ответ 4

Рассмотрим следующий пример, где использование get или pop имеет значение:

Начнем с get:

class Foo(object):
    def __init__(self, foo_param=None):
        print("In Foo: {}".format(foo_param))

class Bar(Foo):
    def __init__(self, **kwargs):
        bar_param = kwargs.get('bar_param')
        print("In Bar: {}".format(bar_param))
        super(Bar, self).__init__(**kwargs)

bar = Bar(foo_param='F', bar_param='B')

Этот фрагмент кода вызывает исключение TypeError:

TypeError: __init__() got an unexpected keyword argument 'bar_param'

Когда Bar исполняет super(Bar, self).__init__(**kwargs) он пересылает Foo тот же самый dict, который он получил: {foo_param='F', bar_param='B'}. Затем Foo вызывает TypeError поскольку входные параметры не соответствуют его интерфейсу.

Если вы pop bar_param перед выполнением вызова super, Foo только recives его необходимый входной параметр foo_param, и все идет отлично.

class Foo(object):
    def __init__(self, foo_param=None):
        print("In Foo: {}".format(foo_param))

class Bar(Foo):
    def __init__(self, **kwargs):
        bar_param = kwargs.pop('bar_param')
        print("In Bar: {}".format(bar_param))
        super(Bar, self).__init__(**kwargs)

bar = Bar(foo_param='F', bar_param='B')

Выход:

In Bar: B
In Foo: F