Classes in Python
General points
- We don’t need to use
new
when instantiating an instance of a class. - All properties and methods must be defined in the constructor. This is in contrast to JavaScript where the properties in the constructor are those we want to initialise when the object is created and where there may be other properties and methods that are used outside of the instantiation process.
- In contrast to TypeScript and other OOP languages it is not necessary to declare the properties you wish to define in the constructor, outside of the constructor. As long as they are defined in the constructor they are accessible.
Class properties
In contrast to other languages, you do not need to declare any properties you wish to use in the class at the top before you can assign to them. This is true whether you define them in the constructor or not.
Instead, you can create properties just by invoking self.some_property_name
in the course of your code and Python will create the variable implicitly.
For continuity with other languages you may however define them at the top of the class if you wish.
Basic syntax
class Person:
""" An example class to hold a persons name and age"""
def __init__(self, name, age):
self.name = name
self.age = age
def birthday(self):
print('Happy birthday you were', self.age)
self.age += 1
print('You are now', self.age)
p1 = Person('John', 36)
p2 = Person('Thomas', 34)
print(p1)
print(p2)
print(p1.name)
# John
Key points to note:
- The
__init__
method is the constructor function and must exist on every class to define the properties of the class self
is a reference to the class itself and the object it will create, akin tothis
in other languages- You must pass
self
as a parameter to every method (this is a difference from JS) - As with functions, we can use docstrings to document the class. What you write here will show up in Intellisense etc
Private, protected members and methods
As Python is not strictly typed the property accessors are not actually real and won’t throw errors if violated. However there is a syntax convention.
Private
__self.property
def __private method(self)...
Protected
_self.property
def _protected method(self)...
More complex class
class Person:
""" An example class to hold a persons name and age"""
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name + ' is ' + str(self.age)
def birthday(self):
print ('Happy birthday you were', self.age)
self.age += 1
print('You are now', self.age)
def calculate_pay(self, hours_worked):
rate_of_pay = 7.50
if self.age >= 21:
rate_of_pay += 2.50
return hours_worked * rate_of_pay
def is_teenager(self):
return self.age < 20
Object references
When you log a class you get a reference to its hexadecimal Memory reference.
p1 = Person('John', 36)
p2 = Person('Thomas', 34)
print(p1)
print(p2)
# <__main__.Person object at 0x102e75510>
# <__main__.Person object at 0x102e75511>
This shows each object is unique. You can also generate a specific ID with the id()
method:
print(id(p1))
print(id(p2))
# 4379088272
# 4379088656
Copying objects
The same principle that applies to copying functions applies to copying objects created through classes: redeclaration results in a duplicate entity. Thus changes to the duplicate will affect the original.
This becomes obvious when you use id()
but otherwise might not be apparent. To copy you should therefore declare a new instance of the class.
The str
method
The memory reference isn’t very helpful for viewing the data contents. To get around this we can use the builtin __string__
method which automatically logs whatever properties you put in there:
class Person:
""" An example class to hold a persons name and age"""
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name + ' is ' + str(self.age)
p3 = Person('Thomas', 34)
print(p3)
# Thomas is 34
Deleting objects
You might want to delete an object reference because:
- the variable referencing the object goes out of scope
- the variable is set to
None
After the del
statement is applied to a variable that holds an object, the object will no longer be available and any attempt to reference it will result in an error.
p1 = Person('J-Man', 76)
del p1