Basic class definition:
Classes are blueprints for creating objects in Python.
They bundle data (attributes) and behavior (methods), enabling object-oriented programming concepts like encapsulation, inheritance, and polymorphism.
-
Defining a class:
__init__: this constructor method is called automatically when an instance of the class is created.
self: is a reference to the current instance. It is automatically passed to methods.
Instance variables: they are variables defined with self and are accessible to all methods in the class and to all instances of the class.
class Math:
# class variable (shared by all instances)
name = 'Simple Math'
def __init__(self, i, j):
# instance variables
self.i = i
self.j = j
def set_i(self, i):
self.i = i
def set_j(self, j):
self.j = j
def add(self):
return self.i + self.j
def multiply(self):
return self.i * self.j
@classmethod
def get_name(cls):
return cls.name
@staticmethod
def validate_name(name):
return isinstance(name, str)
# string representation (if not defined, __repr__ is used)
def __str__(self):
return f"Math({self.i}, {self.j})"
# developer representation (also used as string representation if __str__ is not defined)
def __repr__(self):
return f"Math(i={self.i}, j={self.j})"
-
Creating an instance:
math1 = Math(2, 3)
-
Calling methods:
print(math1.add()) # Output: 5
print(math1.multiply()) # Output: 6
-
Accessing attributes:
print(math1.i) # Output: 2
print(math1.j) # Output: 3
-
Modifying attributes:
math1.i = 3
math1.set_j(7)
print(math1.add()) # Output: 10
print(math1.multiply()) # Output: 21
-
String representation
# string representation
print(math1) # Output: Math(3, 7)
# developer representation
print(repr(math1)) # Output: Math(i=3, j=7)
-
Using class/static methods/attributes
# access class variable
print(Math.name) # Output: Simple Math
# access class method
print(Math.get_name()) # Output: Simple Math
# access static method
print(Math.validate_name("Math")) # Output: True
Property decorators:
class Audit:
def __init__(self, msg):
self._msg = msg
@property
def message(self):
return self._msg
@message.setter
def message(self, msg):
self._msg = msg
audit = Audit('Hello')
# access property
print(audit.message) # Output: Hello
# set property
audit.message = "Python"
print(audit.message) # Output: Python
Inheritance:
Inheritance allows a class to inherit attributes and methods from a parent class.
-
Defining a subclass:
class Operations(Math):
def __init__(self, i, j):
super().__init__(i, j)
self.code = 'undefined'
# define new method
def set_code(self, code):
self.code = code
# define new method
def calculate(self, code='add'):
if code == 'add':
return super().add()
elif code == 'multiply':
return super().multiply()
else:
return 'Unknown operation'
-
Creating an instance of the subclass:
operation = Operations(4, 9)
-
Accessing attributes of the subclass:
print(operation.i) # Output: 4
print(operation.j) # Output: 9
print(operation.code) # Output: undefined
-
Calling methods of the subclass:
# calling parent class method
print(operation.add()) # Output: 13
# calling subclass methods
print(operation.calculate()) # Output: 13
print(operation.calculate('multiply')) # Output: 36
print(operation.calculate('divide')) # Output: Unknown operation
Method overriding:
Subclasses can override methods from their parent class to provide specialized behavior.
-
Overriding methods from the parent class:
class SpecialMath(Math):
def __init__(self, i, j, multiplier=10):
super().__init__(i, j)
self.multiplier = multiplier
# override parent method
def multiply(self):
return self.i * self.j * self.multiplier
-
Calling override methods of an instance of a subclass:
specialMath = SpecialMath(4, 6)
print(specialMath.multiply()) # Output: 240
# custom multiplier
specialMath = SpecialMath(4, 6, 100)
print(specialMath.multiply()) # Output: 2400
Modules and imports
-
Creating a module:
Create a file class_module_1.py that contains the definition of two classes:
$ vi class_module_1.py
class MyClassA():
def __init__(self):
self.name = 'My Class A'
class MyClassB():
def __init__(self):
self.name = 'My Class B'
# Module-level function
def get_module_file_name():
return "class_module_1.py"
-
Import entire module:
Create a file class_import_1.py that imports the module class_module_1 (class_module_1.py):
$ vi class_import_1.py
# all classes defined in the module will be accessible using the prefix class_module_1
import class_module_1
# referencing the classes using the name of the module name as a prefix
myclassa = class_module_1.MyClassA()
myclassb = class_module_1.MyClassB()
print(myclassa.name) # Output: My Class A
print(myclassb.name) # Output: My Class B
# calling module function
print(class_module_1.get_module_file_name()) # Output: class_module_1.py
-
Import specific classes:
Create a file class_import_2.py that imports specific classes defined in the module class_module_1 (class_module_1.py):
$ vi class_import_2.py
# importing the classes MyClassA and MyClassB from the module class_module_1
from class_module_1 import MyClassA, MyClassB
# referencing directly the classes without specifying the module name
myclassa = MyClassA()
myclassb = MyClassB()
print(myclassa.name) # Output: My Class A
print(myclassb.name) # Output: My Class B
-
Import all:
Create a file class_import_3.py that imports all classes defined in the module class_module_1 (class_module_1.py):
$ vi class_import_3.py
# importing all public names from the module class_module_1
from class_module_1 import *
# referencing directly the classes without specifying the module name
myclassa = MyClassA()
myclassb = MyClassB()
print(myclassa.name) # Output: My Class A
print(myclassb.name) # Output: My Class B
# calling module function without prefix
print(get_module_file_name()) # Output: class_module_1.py
-
Module aliases
Using the keyword as to define an alias for a module.
Create a file class_import_4.py that imports the module class_module_1 (class_module_1.py) and give it an alias f1:
$ vi class_import_4.py
# defining the alias f1 for the module class_module_1
import class_module_1 as f1
# referencing the class MyClassA using the alias of the module as a prefix
myclassa = f1.MyClassA()
myclassb = f1.MyClassB()
print(myclassa.name) # Output: My Class A
print(myclassb.name) # Output: My Class B
# calling module function using prefix
print(f1.get_module_file_name()) # Output: class_module_1.py
-
Class aliases:
Using the keyword as to define an alias for a class.
Create a file class_import_5.py that imports specific classes defined in the module class_module_1 (class_module_1.py) and give them aliases:
$ vi class_import_5.py
# defining the alias A for the class MyClassA and the alias B for the class MyClassB
from class_module_1 import MyClassA as A, MyClassB as B
# referencing directly the classes using its alias A
myclassa = A()
myclassb = B()
print(myclassa.name) # Output: My Class A
print(myclassb.name) # Output: My Class B