Python: Difference between kwargs.pop() and kwargs.get() Python: Difference between kwargs.pop() and kwargs.get() python python

Python: Difference between kwargs.pop() and kwargs.get()


get(key[, default]): return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

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

pop(key[, default]) if key is in the dictionary, remove it and return its value, else return default. If default is not given and key is not in the dictionary, a KeyError is raised.

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

NB: Regarding best practice question, I would say it depends on your use case but I would go by default for .get unless I have a real need to .pop


The difference is pop also removes the item from the dict.

There is no best practice. Use the one which is more convenient for your particular use case.

Most times, all you need is getting the value.

Other times, you want to make sure no extra/unexpected kwargs are provided. In this case, it is convenient to use pop. E.g.:

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


Consider the next example, where the use of get or pop makes a difference:

Let's begin with 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')

This code snippet raises TypeError exception:

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

When Bar executes super(Bar, self).__init__(**kwargs) it is forwarding to Foo the same dict he has recived: {foo_param='F', bar_param='B'}. Then Foo raises TypeError because input paramteres doesn't respect its interface.

If you pop bar_param before executing the call to super, Foo only recives its required input parameter foo_param, and all goes fine.

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')

Output is:

In Bar: BIn Foo: F