In this post, we are going to discuss Python classes and type.
Since Python is an object-oriented language, everything is an object and a descendant of a class.
But, what you might not know, is that every class is itself descendant of another class known as type.
In Python, we have the built-in type()
function that lets you view the type of any object in Python.
Take a look at the example below:
name = "Mike"print(type(name))
We see that the type of name
is a string.
Now, let’s try building our own class.
We are going to build a class called Fruit
and instantiate descendant fruits from our Fruit
class.
class Fruit:def __init__(self, color, shape):self.color = colorself.shape = shapedef show_characteristics(self):characteristics = [self.shape, self.color]return characteristics
We know that we can instantiate a fruit from our Fruit
class and we will have descendant.
Earlier, we mentioned that even classes are descendant of another class above them. This means that strings, integers, and our Fruit
class has a higher class above it.
When you inspect Fruit
, or a string object like our nametype()
function, it will return the parent of that object to you.
But what will happen if we try to get the type of our Fruit
class itself?
class Fruit:def __init__(self, color, shape):self.color = colorself.shape = shapedef show_characteristics(self):characteristics = [self.shape, self.color]return characteristicsprint(type(Fruit))
You will get <class 'type'>
as an output. If you try to execute it on str
, int
, type
, or other Python classes, you will get <class 'type'>
.
This is because all classes and objects inherit from the type
class above everything else. Therefore, it is possible to re-create our fruit class directly from type
.
type
If you look for type
in the Python help console, you will see a description of the arguments that type
takes in order to create a class.
It is worth noting that
type
takes either 1 or 3 arguments. When a single argument is passed, it will return the class from which the object inherits. When 3 arguments are passed, it returns new class to you with the characteristics and attributes you passed in as last argument. More on this below.
str
, then you would pass a tuple as the second argument.Now, let’s create our class. We are going to recreate the same Fruit
class as above.
def fruit_init(self, shape, color):self.shape = shapeself.color = colordef show_characteristics(self):characteristics = [self.color, self.shape]return characteristicsfruit_class = type("FruitClass", (), {"__init__": fruit_init, "show_characteristics": show_characteristics})
Let’s explore what is happening here.
We are creating a class called FruitClass
, which inherits from no other class (thus the empty tuple).
Our class has some methods like init
and show_characteristics
, which map to the functions we created above.
We created those functions above because it will be hard to fit them into the dictionary, but you could make use of lambda expressions there.
What we end up with is a class that we can use. Let’s try it out.
def fruit_init(self, shape, color):self.shape = shapeself.color = colordef show_characteristics(self):characteristics = [self.color, self.shape]return characteristicsfruit_class = type("FruitClass", (), {"__init__": fruit_init, "show_characteristics": show_characteristics})orange = fruit_class("spherical", "orange")print(orange.show_characteristics())
If you have knowledge of the above underlying functioning in Python, you will be able to better understand the behavior of objects and some classes in Python. With this, you can even define your own blueprints for creating other classes and types, just by creating a class that inherits from the type
class above.
This will give you the power to be able to define your own behavior for objects, and even set rules on what happens when a new object is created.