Python Object Oriented
J. Merhej
Outline
Classes Inheritance
Defining classes Print an object
Using classes issubclass()
Encapsulation
isinstance()
Inheritance and Subclasses
is operator
Variables
Multiple inheritance
Instance variables
Private variables Creating your own
Class variables exceptions
Class built-in functions Cisco: MODULE 3: OBJECT-
Methods ORIENTED PROGRAMMING
Inner life of classes and
objects
Introspection and Reflection
11/04/2024 Python Object Oriented 2
Classes
Defining classes
Using classes
Encapsulation
Inheritance and Subclases
Defining Classes
class name:
"documentation"
statements
-or-
class name(base1, base2, ...):
...
Most, statements are method definitions:
def name(self, arg1, arg2, ...):
...
May also be class variable assignments
11/04/2024 Python Object Oriented 4
Using Classes
To create an instance, simply call the class object:
x = Stack() # no 'new' operator!
To use methods of the instance, call using dot notation:
x.empty()
x.push(1)
To inspect instance variables, use dot notation:
x.items
11/04/2024 Python Object Oriented 5
Classes
11/04/2024 Python Object Oriented 6
Stack Example – Procedural Vs OO approach
stack = [] class Stack:
def push(val): def __init__(self):
self.__stack_list = []
stack.append(val)
def push(self, val):
def pop(): self.__stack_list.append(val)
val = stack[-1]
del stack[-1] def pop(self):
val = self.__stack_list[-1]
return val
del self.__stack_list[-1]
push(3) return val
push(2) stack_object = Stack()
push(1) stack_object.push(3)
stack_object.push(2)
print(pop())
stack_object.push(1)
print(pop())
print(stack_object.pop())
print(pop()) print(stack_object.pop())
print(stack_object.pop())
11/04/2024 Python Object Oriented 7
Encapsulation in Python
When any class component has a name starting with two underscores (__), it
becomes private - this means that it can be accessed only from within the class.
You cannot see it from the outside world. This is how Python implements the
encapsulation concept.
class Stack: class Stack:
def __init__(self): def __init__(self):
self.stack_list = [] self.__stack_list = []
stack_object = Stack() stack_object = Stack()
print(len(stack_object.stack_list)) print(len(stack_object.__stack_list))
--- 0
11/04/2024 Python Object Oriented 8
Class Inheritance
11/04/2024 Python Object Oriented 9
Class Inheritance
class Stack: def push(self, val):
def __init__(self): self.__sum += val
self.__stack_list = [] Stack.push(self, val)
def push(self, val): def pop(self):
self.__stack_list.append(val) val = Stack.pop(self)
self.__sum -= val
def pop(self): return val
val = self.__stack_list[-1]
del self.__stack_list[-1]
return val stack_object = AddingStack()
for i in range(5):
class AddingStack(Stack): stack_object.push(i)
def __init__(self): print(stack_object.get_sum())
Stack.__init__(self)
self.__sum = 0 for i in range(5):
print(stack_object.pop())
def get_sum(self):
return self.__sum
11/04/2024 Python Object Oriented 10
Variables
Instance variables
Private variables
Class variables
11/04/2024 Python Object Oriented 11
Instance Variables
Each object carries its own set of properties - they don't interfere with
one another in any way. Such variables (properties) are called instance
variables.
Modifying an instance variable of any object has no impact on all the
remaining objects.
Python objects, when created, are gifted with a small set of predefined
properties and methods. Each object has got them, whether you want
them or not. One of them is a variable named __dict__ (it's a
dictionary).
The variable contains the names and values of all the properties
(variables) the object is currently carrying. Let's make use of it to safely
present an object's contents.
11/04/2024 Python Object Oriented 12
Instance Variables
class ExampleClass:
def __init__(self, val = 1):
self.first = val
def set_second(self, val):
self.second = val
example_object_1 = ExampleClass()
example_object_2 = ExampleClass(2)
example_object_2.set_second(3)
example_object_3 = ExampleClass(4)
example_object_3.third = 5
print(example_object_1.__dict__)
print(example_object_2.__dict__)
print(example_object_3.__dict__)-
{'first': 1}
{'first': 2, 'second': 3}
{'first': 4, 'third': 5}
11/04/2024 Python Object Oriented 13
Private variables
class ExampleClass: Once added two
def __init__(self, val = 1): underscores (__) in front
self.__first = val of variable makes the
instance variable private -
def set_second(self, val = 2):
self.__second = val
it becomes inaccessible
from the outer world.
example_object_1 = ExampleClass()
print(example_object_1._ExampleClass__first)
example_object_2 = ExampleClass(2) In this case, Python puts a
class name before your
example_object_2.set_second(3) name; it puts an
example_object_3 = ExampleClass(4) additional underscore at
example_object_3.__third = 5
the beginning.
print(example_object_1.__dict__)
print(example_object_2.__dict__)
print(example_object_3.__dict__) TRY IT
11/04/2024 Python Object Oriented 14
Class variables
A class variable is a property which exists in just one
copy and is stored outside any object.
Note: no instance variable exists if there is no object in
the class; a class variable exists in one copy even if
there are no objects in the class.
Class variables aren't shown in an object's __dict__
(this is natural as class variables aren't parts of an
object).
a class variable always presents the same value in all
class instances (objects)
11/04/2024 Python Object Oriented 15
Class variables
class ExampleClass:
counter = 0
def __init__(self, val = 1):
self.__first = val
ExampleClass.counter += 1
example_object_1 = ExampleClass()
example_object_2 = ExampleClass(2)
example_object_3 = ExampleClass(4)
print(example_object_1.__dict__, example_object_1.counter)
print(example_object_2.__dict__, example_object_2.counter)
print(example_object_3.__dict__, example_object_3.counter) --
{'_ExampleClass__first': 1} 3 {'_ExampleClass__first': 2} 3
{'_ExampleClass__first': 4} 3
11/04/2024 Python Object Oriented 16
Class Built-In functions
11/04/2024 Python Object Oriented 17
Checking an attribute's existence
class ExampleClass: class ExampleClass:
def __init__(self, val): def __init__(self, val):
if val % 2 != 0: if val % 2 != 0:
self.a = 1 self.a = 1
else: else:
self.b = 1 self.b = 1
example_object = ExampleClass(1)
example_object = ExampleClass(1) print(example_object.a)
print(example_object.a)
print(hasattr(example_object, 'b'))
try: print(hasattr(ExampleClass, ‘a'))
print(example_object.b)
except AttributeError:
pass 1
False
--1 False
11/04/2024 Python Object Oriented 18
Built-in class functions
hasattr(obj,name) to check if an attribute exists or
not.
getattr(obj, name[, default]) : to access the attribute of
object.
setattr(obj,name,value) : to set an attribute. If attribute
does not exist, then it would be created.
delattr(obj, name) : to delete an attribute.
11/04/2024 Python Object Oriented 19
Methods
Inner life of classes and objects
Introspection and Reflection
11/04/2024 Python Object Oriented 20
Methods
As you already know, a method is a function embedded inside a
class. There is one fundamental requirement - a method is
obliged to have at least one parameter (there are no such thing as
parameter less methods - a method may be invoked without an
argument, but not declared without parameters).
The first (or only) parameter is usually named self. We suggest
that you follow the convention - it's commonly used, and you'll
cause a few surprises by using other names for it.
The name self suggests the parameter's purpose - it identifies the
object for which the method is invoked.
11/04/2024 Python Object Oriented 21
Methods – Self parameter
class Classy: class Classy:
def __init__(self, value): varia = 2
self.var = value def method(self):
print(self.varia, self.var)
obj_1 = Classy("object")
obj = Classy()
print(obj_1.var) - ‘object’ obj.var = 3
obj.method() 2 3
11/04/2024 Python Object Oriented 22
Inner life of classes and objects
__dict__ is a dictionary of object or class variables
Another built-in property worth mentioning is __name__,
which is a string containing the name of the class.
Function type(), which is able to find a class which has
been used to instantiate any object.
__module__ is a string- it stores the name of the module
which contains the definition of the class.
__bases__ is a tuple. The tuple contains classes (not class
names) which are direct superclasses for the class.
11/04/2024 Python Object Oriented 23
Inner life of classes and objects
class Classy: class Classy: class Classy:
varia = 1 pass pass
def __init__(self):
self.var = 2
print(Classy.__name__) print(Classy.__module__)
def method(self): obj = Classy() obj = Classy()
pass print(type(obj).__name__) print(obj.__module__)
def __hidden(self): Classy _main__
pass Classy __main__
obj = Classy()
print(obj.__dict__)
print(Classy.__dict__)
TRY IT
11/04/2024 Python Object Oriented 24
Inner life of classes and objects
class SuperOne:
pass
class SuperTwo:
pass
class Sub(SuperOne, SuperTwo):
pass
def printBases(cls):
print('( ', end='')
for x in cls.__bases__:
print(x.__name__, end=' ')
print(')')
printBases(SuperOne)
printBases(SuperTwo)
printBases(Sub) ( object ) ( object ) ( SuperOne SuperTwo )
11/04/2024 Python Object Oriented 25
Introspection and Reflection
• introspection, class MyClass:
which is the pass
ability of a
program to obj = MyClass()
examine the type obj.a = 1
or properties of obj.b = 2
obj.i = 3
an object at
obj.ireal = 3.5
runtime;
obj.integer = 4
• reflection, which obj.z = 5
goes a step
further, and is def incIntsI(obj):
the ability of a for name in obj.__dict__.keys():
program to if name.startswith('i'):
manipulate the val = getattr(obj, name)
values, if isinstance(val, int):
properties setattr(obj, name, val + 1)
and/or functions
of an object at print(obj.__dict__)
runtime. incIntsI(obj)
print(obj.__dict__) TRY IT
11/04/2024 Python Object Oriented 26
Inheritance
Print an object
issubclass()
isinstance()
is operator
11/04/2024 Python Object Oriented 27
Inheritance – Print an object
When Python needs any class/object to be presented as a string, it tries to invoke a
method named __str__() from the object and to use the string it returns.
The default __str__() method returns the previous string - ugly and not very
informative. You can change it just by defining your own method of the name.
class Star: class Star:
def __init__(self, name, galaxy):
def __init__(self, name, self.name = name
galaxy): self.galaxy = galaxy
self.name = name
self.galaxy = galaxy def __str__(self):
return self.name + ' in ' + self.galaxy
sun = Star("Sun", "Milky Way")
print(sun)
<__main__.Star object at sun = Star("Sun", "Milky Way")
0x79025c7854b0> print(sun)
Sun in Milky Way
11/04/2024 Python Object Oriented 28
Inheritance: issubclass()
class Vehicle:
Issubclass(class1 pass
,class2): can
check if a class LandVehicle(Vehicle):
particular class pass
is a subclass of
any other class.
class TrackedVehicle(LandVehicle):
pass
for cls1 in [Vehicle, LandVehicle, TrackedVehicle]:
for cls2 in [Vehicle, LandVehicle, TrackedVehicle]:
True False False print(issubclass(cls1, cls2), end="\t")
True True False print()
True True True
11/04/2024 Python Object Oriented 29
Inheritance: class Vehicle:
pass
isinstance() class LandVehicle(Vehicle):
pass
Isinstance(obj,cls
) : to detect if an class TrackedVehicle(LandVehicle):
object is an pass
instance of a
class
my_vehicle = Vehicle()
my_land_vehicle = LandVehicle()
my_tracked_vehicle = TrackedVehicle()
for obj in [my_vehicle, my_land_vehicle,
my_tracked_vehicle]:
for cls in [Vehicle, LandVehicle, TrackedVehicle]:
print(isinstance(obj, cls), end="\t")
print() ------
11/04/2024 Python Object Oriented 30
class SampleClass:
def __init__(self, val):
Inheritance: is operator self.val = val
The is operator checks
whether two variables object_1 = SampleClass(0)
(object_one and object_two object_2 = SampleClass(2)
here) refer to the same object_3 = object_1
object_3.val += 1
object.
Assigning a value of an print(object_1 is object_2)
object variable to another print(object_2 is object_3)
variable doesn't copy the print(object_3 is object_1)
print(object_1.val, object_2.val, object_3.val)
object.
string_1 = "Mary had a little "
string_2 = "Mary had a little lamb"
False
string_1 += "lamb"
False
True print(string_1)
1 2 1
Mary had a little lamb print(string_1 == string_2, string_1 is string_2)
True False
11/04/2024 Python Object Oriented 31
Inheritance Example
super() function, which accesses the superclass without needing to know its name:
class Super: class Super:
supVar = 1
def __init__(self, name):
self.name = name
class Sub(Super):
def __str__(self): subVar = 2
return "My name is " + self.name + "."
obj = Sub()
class Sub(Super):
def __init__(self, name): print(obj.subVar)
Super.__init__(self, name) print(obj.supVar)
obj = Sub("Andy")
print(obj)
11/04/2024 Python Object Oriented 32
100 101 102
Three level Inheritance 200 201 202
300 301 302
class Level1: class Level3(Level2):
variable_1 = 100 variable_3 = 300
def __init__(self): def __init__(self):
self.var_1 = 101 super().__init__()
self.var_3 = 301
def fun_1(self):
return 102 def fun_3(self):
return 302
class Level2(Level1):
variable_2 = 200
def __init__(self): obj = Level3()
super().__init__()
self.var_2 = 201 print(obj.variable_1, obj.var_1, obj.fun_1())
print(obj.variable_2, obj.var_2, obj.fun_2())
def fun_2(self): print(obj.variable_3, obj.var_3, obj.fun_3())
return 202
11/04/2024 Python Object Oriented 33
Multiple Inheritance
class SuperA:
var_a = 10
def fun_a(self):
return 11
class SuperB: 10 11
var_b = 20 20 21
def fun_b(self):
return 21
class Sub(SuperA, SuperB):
pass
obj = Sub()
print(obj.var_a, obj.fun_a())
print(obj.var_b, obj.fun_b())
11/04/2024 Python Object Oriented 34
Multiple Inheritance
class Level1:
var = 100
def fun(self):
return 101
class Level2(Level1):
200 201
var = 200
def fun(self):
return 201
class Level3(Level2):
pass
obj = Level3()
print(obj.var, obj.fun())
11/04/2024 Python Object Oriented 35
Multiple Inheritance
class Left:
var = "L"
var_left = "LL" Python looks for object components in
def fun(self): the following order:
return "Left"
• inside the object itself;
class Right: • in its superclasses, from bottom to
var = "R" top;
var_right = "RR"
• if there is more than one class on a
def fun(self):
return "Right" particular inheritance path, Python
scans them from left to right.
class Sub(Left, Right):
pass
obj = Sub() L LL RR Left
print(obj.var, obj.var_left, obj.var_right,
obj.fun())
11/04/2024 Python Object Oriented 36
class MyZeroDivisionError(ZeroDivisionError):
Creating your own pass
exceptions def do_the_division(mine):
if mine:
print('some worse news')
raise MyZeroDivisionError("some worse news")
My division by zero
else:
False
print('some bad news')
some bad news
raise ZeroDivisionError("some bad news")
Division by zero
True
for mode in [False, True]:
some worse news
try:
Division by zero
print(mode)
some bad news
do_the_division(mode)
Original division by
except ZeroDivisionError:
zero
print('Division by zero')
some worse news
My division by zero
for mode in [False, True]:
try:
do_the_division(mode)
except MyZeroDivisionError:
print('My division by zero')
except ZeroDivisionError:
print('Original division by zero')
11/04/2024 Python Object Oriented 37
class PizzaError(Exception):
Creating your own def __init__(self, pizza, message):
Exception.__init__(self, message)
exceptions self.pizza = pizza
class TooMuchCheeseError(PizzaError):
def __init__(self, pizza, cheese, message):
Pizza ready!
PizzaError.__init__(self, pizza, message)
too much cheese : 110
self.cheese = cheese
no such pizza on the
menu : mafia
def make_pizza(pizza, cheese):
if pizza not in ['margherita', 'capricciosa', 'calzone']:
raise PizzaError(pizza, "no such pizza on the menu")
if cheese > 100:
raise TooMuchCheeseError(pizza, cheese, "too much
cheese")
print("Pizza ready!")
for (pz, ch) in [('calzone', 0), ('margherita', 110), ('mafia', 20)]:
try:
make_pizza(pz, ch)
except TooMuchCheeseError as tmce:
print(tmce, ':', tmce.cheese)
except PizzaError as pe:
print(pe, ':', pe.pizza)
11/04/2024 Python Object Oriented 38
Python vs Java
11/04/2024 Python Object Oriented 39
Python vs. Java
Hello World
String Operations
11/04/2024 Python Object Oriented 40
Python vs. Java
Collections
11/04/2024 Python Object Oriented 41
Python vs. Java
Class and Inheritance
11/04/2024 Python Object Oriented 42