Answering a few Pythonic questions

In today’s blog I would be going through a few questions:

  • Which is faster in python — Searching in a list or a dictionary. And why?
  • How can we get the code of a python object?
  • What are the ways to make python code work faster?
  • What is exec function and how we can use it?
  • What are metaclasses and dataclasses in python?
  • Is python interpreted or compiled? Are there ways to compile the code.
  • What is __call__ method in python?

Searching element in a list is much slower when we compare to searching in the dictionary. This is because the dictionary is uses a key-value mapping. So let’s say if you want to search anything we can just type in the key and we will get the value in O(1) time.

This is not the case with lists. Because to find the value in lists we have to actually traverse the list.

But there are cases when we don’t have key-value pairs. For this we can use the set data structure wherever possible. It also uses hashing like dictionary. The one catch with these time efficient data structures is that they take a little overhead for storing the lookup table for storing the key-value or hash values.

Almost everything in python is an object so there are times we need to see the code that went inside the python object.

For this we need to import the inspect module and use the getsource() method.

Since we know that the object is just an instance of a class. This method returns the source code of the class we specify. This is an important when we don’t understand the working of a certain code. This is possible only because python is an open source language. So we can look at the source code and see how things might be working behind the scenes.

When I run the following commands

We can see that the output is nothing but the source code of the class and function.

You might think that how is class an object but I would be explaining about this ahead when I talk about meta classes

Apart from that the inspect module has various other methods to retrieve just the variables or class methods etc. You can find the full details here.

One of the primary reasons why python tends to be slower than traditional languages like java and c++ is because it is dynamically typed as opposed to the statically typed languages.

So what is the difference?

Whenever we define variables in python we don’t have to specify the type of variables we are going to store in it. This creates an overhead on the python interpreter because it has to perform the the task of identifying the data type when running the code.

Also when we compile the code in java or C, all the checks are done before runtime. So if there is an error we get the error before running. However python has these heaps of checks during runtime. This also adds an overhead on python interpreter which in turn hampers the speed of execution. For the moment let’s not consider that this feature is helpful because we are just comparing the speed right now and not the overall productivity.

There are various tips that can however boosts the speed of python code:

  • We should try to reduce the memory footprint of the program.
  • Many builtin functions are written internally in C. Which is a much faster language. So we should try using these whenever possible. For example using a for loop to calculate the maximum should be replaced by using max().
  • Also let’s say you are using numpy array and you don’t need any other function from that library. So

from numpy import array

makes more sense than

import numpy

  • Talking about data science perspective we should try using numpy arrays over lists. This is because numpy arrays are created in contiguous locations like C unlike lists.

These are a few tips to make the code run faster.

Exec function allows us to execute the code dynamically.

Exec function accepts the string as a parameter and executes it during runtime. This is a very interesting concept. As using this we can give the users a freedom to enter the python command dynamically as they run the code.

The syntax of the command is :

exec(<string_command>,<global_variables_dictionary>,<local_variables_dictionary>)

The global variables and local variables and when they are not specified the exec defaults the global variables.

Let’s see it in action

The output of the give

  • In the first exec command to print the “x” I did not specify the global variable x so it uses it by default to print “5*x”.
  • In the next example to print the variable y. I specified it’s value as a local variable. This is the reason why it prints the value.

Now I would like to portray internal working of exec command.

When I executed the exec command using “a” as local variable there was no change in the value of “a” while when we use it as a global variable it changes the value of “a” in the global scope.

A metaclass is a class whose instances are classes. Like a class defines the behavior of the instances of the class, a metaclass defines the behavior of classes and their instances.

So let’s see if there is a metaclass in python.

Hmm. This seems interesting. So “a” belongs to class “int”. The int belongs to class “type” and so does “type”.

So type is a very special class or meta class in python. The the last line of the above code snippet demonstrates that type is also an instance of metaclass type.

Every Python class that we create is attached to a default metaclass and Python abstracts this.

Every class is has only one meta class.

Dataclasses are a new feature added in python 3.7.

As the name suggests we use the data classes to store data. This helps in managing data easily. One special highlight of the dataclass is that it can be defined without a constructor. This means it can work without the __init__() function.

Python is an interpreted language. However there is a catch. When we run the python code. It internally compiles and then the interpreter interprets it.

To quote the documentation of python which should be taken as holy grail.

Python is an interpreted language, as opposed to a compiled one, though the distinction can be blurry because of the presence of the bytecode compiler. This means that source files can be run directly without explicitly creating an executable which is then run.

The compiled languages tend to be faster than the interpreted languages. So in places where we want to run the code faster we prefer it to be compiled.

Whenever we call the instance like we do a funtion, the __call method runs. We never come to know this because we usually don’t use it while calling. The __call__ keyword is reserved when creating classes in python.

Here you can see when I just used the class object as a function the __call__ method is called implicitly.

Python is a very user friendly language and often hides less important information inside the hood.

Reference links

Thanks :)

Tech enthusiast