Activation of neurons Welcome back to the discussion on deep learning. We could have a basic idea of what is deep learning in the...
Handy Python Features – Part 01admin
Python is a powerful language and there are many handy built-in features. Decorators are one of them. You might have scene decorators in python sources as in the following example.
Decorators are functions that wrap functions and change their behavior. Python describes decorators with PEP-0318. Before discussing what are the decorates and how could they be used, we need to understand what are the functions in python and the way python treats them.
Simply, a function can take arguments and do a job on that. For example, print function in the above example takes a string input as an argument and print it. There are functions that do not accept any argument. Some functions return output and some do not.
Python defines a function when it sees the keyword def. Functions are also allowed to be defined inside a function as follows. Those are called inner functions.
The function print_greeting() has two inner functions. One of them is invoked based on the argument uppercase when it is called.
Functions in python are treated as first-class objects. Therefore functions can be passed as arguments to another function just like as strings, integers or any other object. The following example shows how to pass a function into a function.
The Function run_any_function(function) takes any function as an argument and invokes it. Here it takes the function print_hi() .
Functions can also be returned from a function as the output.
The function get_capable_function(uppercase) returns a function based on the argument uppercase. If the argument is true, the function print_text_uppercase(text) is returned and the function print_text(text) otherwise.
Now we have the background to discuss how do decorators work.
Decorators are functions that wrap a function and change their behavior. These functions take a function as an argument. They have an inner function defined which can invoke the function taken as the argument changing its behavior. The inner function is returned as the output.
The above example shows basic decorator. The function print_hi_and_name(name_only_function) takes the function print_name() as an argument. It is called by the inner function add_hi()which changes the behavior by printing “Hi”. The inner function is returned hence the function print_name can be re-declared with the decorator function.
There is a more concise short-cut way to achieve the same result instead of re-declaring the function as we did in line 12 in the above example.
Functions with arguments
The function print_name() prints a hard-coded value. Suppose we need to pass a name as an argument into that function and the new function becomes print_name(name) now. But the inner function which invokes this does not know the arguments required by the function. It should also be changed accordingly which would give an error otherwise.
The inner function add_hi() in the above example is modified as add_hi(name) which becomes able to take the argument name which could then be passed to the function print_name(name).
We also can change the functionprint_hi_and_name(name_only_function) to print_greeting_and_name(name_only_function, greeting) which can then take an extra argument greeting as follows.
Arguments as *args and **kwargs
Suppose we needed to modify the function print_name(name) to print a salutation before the name. The modified function would then take a new argument salutation.
Previously we had to modify the inner function to take the arguments required by the decorated function. The same thing is required for the new argument as well. This is not accepted and not a good practice. The argument that should be passed to the decorated function should not be known by the decorator.
We can use a trick for that. The trick is *args and **kwargs. The function add_greeting(name) can be changed to add_greeting(*args,**kwargs) and then the function name_only_function(name) can be called as name_only_function(*args,**kwargs) as follows. We can now change the function print_name(name) as print_name(salutation, name).
Languages like Java has access modifiers which are used to control the scope of a method. Methods can be made private by using the keyword private. But python has no such concept.
We can write a decorator to make private functions in a class unable to be accessed outside. We just need to check whether the private function is called from outside or inside the class.
The decorator can be used for isolating private functions as follows.
The decorated functions with @private_function are only allowed to be called inside the class. An exception is raised if those are called from outside.
Further reading …
Decorators are handy. Those can be used with classes as well. Singleton pattern can be implemented using decorators. I would suggest you read more on that.