Python Features You Should Know (That can Save you A Lot of Time !)
Tags: python, tutorial
Published: 2021-01-19 05:45:33


Using python over the years, I came across some useful features that would have saved me a lot of time if I had known about them a little bit earlier. These little python gems can help keep your code more DRY( ***D***o Not ***R***epeat ***Y***ourself) and clean.

By the time you are finished with this article, I can guarantee you that you will be using some of these features in your very own python programs.

**Note: You can use any IDE or text editor that you are familiar with ( python’s default IDE is known as “IDLE” and that can also be used). For these features, I will be demonstrating using Visual Studio Code (VS Code) with a python extension.**

_For maximum appreciation, it would be best if you’ve had some experience in using python. However, even if you have never used python before, this article will help you on your python journey. So sit back, relax and enjoy !_

##**Enumerate**

Let’s first start off with Enumerate.

Let’s say you had a list of fruits. You also wanted to loop through all the fruits that are in that list and also keep a track of the position(index) of each fruit in that list using a for-loop.

The following code is an example of this:

![](https://cdn-images-1.medium.com/max/2000/1*Xso_Vf1ELO0FY2G5hgf1Mw.png)

Output:

    0 apple
    1 banana
    2 mango
    3 melon

As you can see we got each fruit in the list with its corresponding index. You could also use a while loop to complete this task but it would also lead to the same issue — a lengthy code .

A better way to solve this issue is to use enumerate.

![](https://cdn-images-1.medium.com/max/2000/1*lDMG_XIiLh2hrvpbtcZucw.png)

Output:

    0 apple
    1 banana
    2 mango
    3 melon

**See, the output is the same!**

We were able to do the same task with less lines of code. But how?

`enumerate(fruit_lst)`. This is where enumerate comes in. Inside our for-loop, `enumerate(fruit_lst)` allows us to keep track of the index of each element (fruit). Each iteration in the loop returns a tuple with the first element being the index and the second element being the current element in the list.

`count,fruit` breaks apart that tuple which contains two elements, assigning the first and second element to them respectively.

It is only fair to imagine that `enumerate` turned `fruit_lst` into a list of tuples as seen below:

    [(0,"apple"),(1,"banana"),(2,"mango"),(3,"melon")]

##**Easier Printing to the Console**

Too many times I have seen developers over complicate printing. Instead of using the typical concatenation or `.format()` method of a string, there is a much easier way.

![](https://cdn-images-1.medium.com/max/2000/1*HBtbWAZKNayPruudTBwrhw.png)

Look how clean and simple the code snippet above is. All it requires is an `f` before any string.

Any variable that needs to be in the string can be encased in-between the double curly braces `{ }` .

Output:

    10 + 20 = 30

##**Keyword Arguments (\**kwargs) and Non-Keyword Arguments(*args)**

You might have come across these two in python’s documentation. A lot of functions in python libraries are implemented using keyword and non-keyword arguments.

**Disclaimer**:

The terms parameters and arguments will be used quite frequently throughout this section and onwards in this article. From a function’s perspective:

_A parameter is a variable that is listed within the parentheses in a function’s definition. However, an argument is a value that is sent to the function whenever it is called._

![parameters vs arguments](https://cdn-images-1.medium.com/max/2000/1*nU5M6nPXbPZlRzXsmQPYaQ.png) <p align="center">parameters vs arguments</p>

Let’s Begin.

###**Non-Keyword Arguments(*args)**

Normally when declaring a function, we have to explicitly declare the number of arguments that are needed for that function.

The function below adds 3 numbers:

![function to add 3 numbers](https://cdn-images-1.medium.com/max/2000/1*4KujYblHRnBBeYD9dVVq8w.png)*function to add 3 numbers*

The function above explicitly declares three arguments **a**, **b** and **c**. No arguments apart from those three can be placed within the function.

Output:

    60

Our output is obvious !

However, let’s say you had no idea how many numbers you wanted to add. It could have been four numbers, maybe two or even one hundred numbers. We therefore want a multi-purpose function that can handle any number of arguments.

This is where the non keyword arguments come in (`*args`).

![](https://cdn-images-1.medium.com/max/2000/1*vgsHOUshSx4mWy7k_x3dgw.png)

Output:

    6
    10
    15
    21

As you can see, the function was was able to handle various amounts of numbers that were thrown at it. This works because of the `*args` declaration. By placing an asterisk(*) to the left of any variable in a function’s parameters you can achieve this goal.

It works by storing all the arguments in a tuple that is assigned to a variable defined in the parameters. In this case `args`.

**Note: `args` is an arbitrary name that was given to the variable. Any name could have been used.**

If you were to print out `args` in the console, the final print statement would have be seen as below:

    (1, 2, 3, 4, 5, 6)

###**Keyword Arguments**

Up next we have keyword arguments. Keyword arguments can be denoted by key-value pairs inside the function arguments.

Keyword arguments are similar to non-keyword arguments. However, the only difference found between them is that keyword arguments use double asterisks(**) to the left of the variable name.

**Note:** The function below uses keyword arguments.

![](https://cdn-images-1.medium.com/max/2000/1*d1AD9rtgksONDhJJpIDZ_g.png)

Output:

    {'name': 'jordan', 'age': 10, 'height': 20}

Keyword arguments are supplied with a key and a value that are separated by an equal sign. Similarly to what is shown in the code snippet above. The corresponding key and value are then stored in a dictionary.

##**Decorators**

Python Decorators. These allow you to add functionalities to an existing function. Decorators allow you to take and modify any function by placing the name of the decorator directly above the function declaration.

Below is a decorator we named `deco`:

    @deco

And this is our normal function:

    def task1():
        print("task 2")

Running the function above will produce the output seen below:

    task 2

Decorators are placed on top of the function. The code snippet below shows how decorators are activated:

    @deco
    def task1():
        print("task 2")

If we were to use this function as is, you will notice something quite interesting.

The function above will produce the following:

    adding functionality before
    task 2
    adding functionality after

Therefore, in adding that decorator we were able to modify the output of the function. But how did this happen?

Let’s look at how we created this decorator:

![](https://cdn-images-1.medium.com/max/2000/1*8ODFf5WqdTL8Tz7oqgV9pg.png)

_Let’s start off with the concept that functions in python are “first class objects’’. This is a fancy term that means that functions can basically work like variables. They can be assigned to and provide a return value. You might think that this is the same across each programming language but it is not. Many programming languages such as Java and C cannot do this._

Okay, so with that premise in mind. Let’s look at the function above.

* The function name `deco` is what we will be calling our decorator.

* Whatever function the decorator is attached to it will be stored in the `f` variable in the function’s parameters. (Remember, functions in python are first class objects).

* The `inner` function located inside the `deco` function is how we modify the `f` function that was passed into the decorator. You can see in the `inner` function where we produced two `print` statements before and after the function call.

* The `f()` will call the existing function that was passed into the decorator.

* We then return the `inner` function. Again, functions are objects so we can return them.

As you can see the decorator modified the function and created a new one than performs additional tasks.

Full code:

![](https://cdn-images-1.medium.com/max/2000/1*87FmjqwVeL6DAwquC1lZsQ.png)

In reality, a decorator is what we call ***syntactic sugar***. This just means that it is a simpler( and sweeter) way of expressing a piece of code. Let’s look at what decorators really are.

![](https://cdn-images-1.medium.com/max/2000/1*S1R_lWNw-GwjKy3jEsSEnA.png)

The code above does the same task as our code before. However, instead of adding our `@deco` to `task1()` , we’ve added the `task1` function as an argument to our `deco` function.

Decorators are just a cleaner way of achieving the same functionalities.

###**Adding Parameters to Decorators**

Here’s the thing. Many times functions have parameters. But how do we handle these functions with parameters?

Let’s add a parameter to our function as shown below:

![](https://cdn-images-1.medium.com/max/2000/1*dR4QRgDGZ7Bwr7LO1SlmUQ.png)

How do we handle this in our decorator ?

![](https://cdn-images-1.medium.com/max/2000/1*yrt11YovnxmKDtxAydpcQw.png)

Due to the fact that we are outputting a new function, the new function that we output would need to have the same number of parameters as the function that was inputted. Hence, the `inner` function needs to have the same parameters as the function that was inputted.

The full code:

![](https://cdn-images-1.medium.com/max/2000/1*WwY_W4HN0UQenC_vMbheDg.png)

Output:

    adding functionality before
    task 10
    adding functionality after

Now, we can add parameters. We should be finished, right? Well, one of the points of a decorator and also in every aspect of coding is to ensure reusability. In using and defining strict parameters to the `inner` function, we’ve forced the decorator to only accept functions with one parameter. This is not very DRY (***D***o Not ***R***epeat ***Y***ourself ) of our code.

To achieve a decorator that will accept various numbers of parameters we will revisit one of the tools we recently just learnt. Our keyword and non-keyword arguments.

With the combination of these two, this will allow the decorator to not be limited by any number of parameters.

![](https://cdn-images-1.medium.com/max/2000/1*bugMjG4nqkKH_2sGq3ixEA.png)

Here we fixed our dilemma by adding `(*args,**kwargs)` to both our `inner` function declaration and our f function call. We then added `*args` to allow the function to have multiple parameters and `**kwargs` for if and when we decided on using any default parameters or key-value pairs.

Now let’s try our decorator with two functions that contain different parameters:

![](https://cdn-images-1.medium.com/max/2000/1*VKG1wDKsAzISdOC1rlM5ig.png)


Output:

    adding functionality before
    task 1
    adding functionality after
    adding functionality before
    task 3
    adding functionality after


<p>&nbsp;</p>

Thank You For Reading :smiley: | Hope you learned something

<a href="https://www.buymeacoffee.com/PlatinumCoder" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>

<p>&nbsp;</p>

##**Summary**
> #**Simplicity at its best !**

Often times in coding, a complex task can be broken down into simpler ones — you just have to look ! It’s the same thing with these python gems as they are coding hacks to help you on your coding journey to make your code easier to read as well as to be more DRY. I definitely encourage you to try these out whenever you’re writing your own python programs.