Classes
Basics
While classes are interwoven into languages like Java or C, you can accomplish almost anything in Python without encountering classes.
We’ll be showing the example before explaining its contents, so don’t worry if you don’t understand what you’re looking at right away.
Anatomy of a Python Class
import math
class Pet:
domesticated = True
def __init__(self, name, age, gender, height, weight, is_fixed=False):
self.name = name
self.age = age
self.gender = gender
self.height = height
self.weight = weight
self.is_fixed = is_fixed
def sound(self):
return(f'Hello there, my name is {self.name}, and I\'m a pet.')
@staticmethod
def calculate_bmi(height, weight):
return(weight / math.pow(height, 2) * 703)
def is_overweight(self):
return(self.calculate_bmi(self.height, self.weight) > 24)
@classmethod
def from_dict(cls, d):
print("In from_dict, and cls is:", cls)
is_fixed = False
if d.get("name"):
name = d.get("name")
if d.get("age"):
age = d.get("age")
if d.get("gender"):
gender = d.get("gender")
if d.get("height"):
height = d.get("height")
if d.get("weight"):
weight = d.get("weight")
if d.get("is_fixed"):
is_fixed = d.get("is_fixed")
return cls(name, age, gender, height, weight, is_fixed)
class Dog(Pet):
def sound(self):
return(f'Ruff ruff!')
Instances and their Attributes
The name of a class immediately follows its declaration — this class is Pet
. We would create an instance/object of Pet
by doing the following:
my_pet = Pet(name="Ziva", age=.25, gender="Female", height=.5, weight=10, is_fixed=True)
The above code works thanks to the __init__
function in Pet
, which allows instances of Pet to be initialized. age
, name
, gender
, height
, weight
, and is_fixed
are instance attributes. In this case, is_fixed
is the only argument with a default value, meaning you must provide information for the other 5 in order for your code to run. We’ll explain the inner workings of __init__
shortly.
Attributes of classes can be accessed using .
followed by the attribute, as in the following examples:
print(my_pet.name)
Ziva
print(my_pet.age)
0.25
Class Attributes
Python classes can have their own attributes independent of any declared objects of that class — notice how domesticated = True
is on its own, outside of __init__
. You can determine class attributes by calling on instances or the class itself.
print(my_pet.domesticated) # via instance of the Pet class
print(Pet.domesticated) # via the class itself
True True
Class Methods
Methods are, broadly speaking, functions that are defined within a class that serve some purpose that might need repeated. All methods have the def
keyword in front of them, short for define. Methods can be called in the same way as attributes. Unlike other languages, Python requires a self
argument in the method declaration to ensure that an instance refers to or changes its own attributes. It is not necessary to include self
anywhere except the method declaration within the class.
sound
and is_overweight
are some of the methods in Pet
.
print(my_pet.sound())
Hello there, my name is Ziva, and I'm a pet.
print(my_pet.is_overweight())
True
Looks like our pet makes some weird sounds and needs some walks.
calculate_bmi
is a static method of Pet
. Static methods don’t take self
or the class as arguments, nor modify the attributes of an instance or class. self
is not passed as the first argument for these methods. Generally, a static method may be appropriate if the method is loosely coupled to the object.
print(Pet.calculate_bmi(50, 120))
33.744
print(my_pet.calculate_bmi(50, 120))
33.774
# this will NOT work, calculate_bmi is not passed `self`
# you will have to provide your own parameters for static methods
print(my_pet.calculate_bmi())
Error in py_call_impl(callable, dots$args, dots$keywords): TypeError: calculate_bmi() missing 2 required positional arguments: 'height' and 'weight' Detailed traceback: File "<string>", line 1, in <module>
from_dict
is a class method of Pet
. Instead of self
, class methods accept cls
as the first argument, and are automatically passed cls
as the first argument when called. cls
is simply the class, which is Pet in this case.
This method specifically takes a dictionary
containing information for every instance attribute in Pet
, then creates a Pet
object from that.
d = {"name": "Ziva", "age": .25, "gender": "Female", "height": .5, "weight": 10, "is_fixed": True}
# Pet and cls are the same:
print(Pet)
<class '__main__.Pet'>
Pet.from_dict(d)
In from_dict, and cls is: <class '__main__.Pet'> <__main__.Pet object at 0x7ff1a2eb3520>
Dunder methods, including __init__
, all start and end with double underscores, and they generally encompass functions that are built-in to the basic object types in Python: __str__
, __add__
, __format__
, and so on.
The idea is that you are able to flesh out your own classes by adapting base Python dunder methods for your own purposes.
Inherited Classes
At the end of our example is Dog
, which is another class that contains Pet
within parentheses. This makes Pet
a parent class for Dog
that hands down its methods and attributes.
Though Pet
appears to be an argument for Dog
, you cannot substitute a Pet
object to initialize Dog
. Child classes effectively clone their parents, overriding certain methods or attributes when necessary. In this case, sound
will have different results depending on if the object is a Pet
or a Dog
.
my_dog = Dog("Ziva", .25, "Female", .5, 10, True)
print(my_pet.sound())
print(my_dog.sound())
Hello there, my name is Ziva, and I'm a pet. Ruff ruff!
print(my_dog.is_overweight())
print(my_dog.domesticated)
True True