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