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]: