Learn about decorators, kwargs and args.
Decorators¶
First Class Objects¶
In [26]:
def outer():
def inner():
print "Inside inner() function."
return inner # This returns a function.
In [27]:
# Here, we are assigning `inner` to the object `call_outer`.
call_outer = outer()
In [28]:
# We can call `call_outer`. This works only because we have an object `call_outer` that contains `inner`.
call_outer()
If we do not return inner, we would get a NoneType error. This is because the inner function is redefined at every outer() call. When we do not return inner, it would not exist when it goes out of scope.
In [29]:
def outer():
def inner():
print "Inside inner() function."
In [30]:
call_outer = outer()
In [31]:
call_outer()
*args¶
*args is used to indicate that positional arguments should be stored in the variable args.
<br > * is for iterables and positional parameters.
In [33]:
def dummy_func(*args):
print args
In [37]:
# * allows us to extract positional variables from an iterable when we are calling a function
dummy_func(*range(10))
In [38]:
# If we do not use *, this would happen
dummy_func(range(10))
In [39]:
# See how we can have varying arguments?
dummy_func(*range(2))
**kwargs¶
** is for dictionaries & key/value pairs.
In [40]:
def dummy_func_new(**kwargs):
print kwargs
In [42]:
dummy_func_new(a=0, b=1)
In [44]:
# Again, there's no limit to the number of arguments.
dummy_func_new(a=0, b=1, c=2)
In [46]:
# You can even leave out any arguments.
dummy_func_new()
In [51]:
# Similar to *args, you can use ** for definition.
new_dict = {'a': '10', 'b': '20'}
new_dict
Out[51]:
In [53]:
dummy_func_new(**new_dict)
In [54]:
# If we do not use **, we would get an error.
dummy_func_new(new_dict)
Decorators¶
Now we have a decent understanding of first class objects, *args and **kwargs, we can show how decorators work. It basically allows us to modify our original function and even replace it without changing the function's code.
In [70]:
def printall(func):
def inner(*args, **kwargs):
print 'Arguments for args: {}'.format(args)
print 'Arguments for kwargs: {}'.format(kwargs)
return func(*args, **kwargs)
return inner
In [71]:
@printall
def random_func(a, b):
return a * b
In [72]:
a = random_func(2, 2)
In [73]:
a
Out[73]:
In [74]:
@printall
def random_func_new():
return 10
In [75]:
random_func_new()
Out[75]: