You are on page 1of 28

CONTENT

1. What is OOP
2. Quiz (true/false)
3. Class Anatomy: attributes and methods
4. Constructor
5. Exercise: Class Point
6. Instance and Class data
7. Exercise
8. Exercise: Class BetterDate
9. (Extra)
10. Class Inheritance
11. Exercise: Class LoggedDF
12. Operator Overloading Comparison
13. Operator overloading: String representation
14. (Extra: Assesment)
15. Error Handling
16. Exercise: function invert_at_index
17. Polymorphism
18. Exercise: Circle-Ellipse Problem
19. Managing Data access: private attributes
20. Exercise: Class BetterDate p-2
21. Properties
22. Exercise class Customer

Exercise: GitHub Link


OBJECT ORIENTED PROGRAMMING IN PYTHON

23. What is OOP

The more data a code uses the more harder it is to think about as just a sequence of steps. Instead we
view it as a collection of objects and patterns of their interactions.

Object = state + behavior

Example a customer may have following data:

Instead of thinking customer data separately, we think of them as one unit, representing a customer. This
is called encapsulation.

The real strength of OOP comes from utilizing classes. Classes like blueprint of objects. In python,
everything is an object. Number, string, dataframes even functions are objects. Every object has a class
and you can use type() on any python object to find the class. help(a) in the console will show the
documentation for the object or class a.

If a is an object then dir(a) list all attributes and methods

24. Quiz (true/false)

1. Attributes encode the state of an object and are represented by variables.

2. .columns is an example of a method of a DataFrame object

3. Object and class are different terms describing the same concept
4. A programming language can be either object oriented or procedural, but not both

5. Object is an abstract template describing the general states and behaviors.

6. Encapsulation is a software design practice of building the data and methods that operate on that data

7. Methods encode behavior of an object are represented by functions

True: 1,6,7

Hints: Concepts of object and class are related, but have a fundamental difference: an object is a particular
representation of a class, while a class is just an abstract pattern.

.columns is not a function. In code, methods are represented by functions, and functions are called with
parentheses. While accessing an attribute can look a lot like calling a function, there are no parentheses.

25. Class Anatomy: attributes and methods

Every method in python have one specialty than functions: it have a arg named self

What is self?

 Classes are templates, how to refer data of a particular object? Self is a stand-in for a particular
object used in class definition.
class Customer:
def identify(self):
….
cust = Customer()
cust.identity(“Luna”)

Here cust.identify(“Luna”) will be interpreted as Customer.identify(cust, “Luna”)

Inside method: self.attribute should remind of the object.attribute syntax

26. Constructor

Constructor __init__() method called every time an object is created. We can define attribute in any
method, or using constructor. Constructor is much useful when an object is associate with lot of data.
Docstrings are displayed when help() is called on the object.

27. Exercise: Class Point

Write a class from scratch

You are a Python developer writing a visualization package. For any element in a visualization, you want
to be able to tell the position of the element, how far it is from other elements, and easily implement
horizontal or vertical flip .

The most basic element of any visualization is a single point. In this exercise, you'll write a class for a point
on a plane from scratch.

Instructions

Define the class Point that has:

 Two attributes, x and y - the coordinates of the point on the plane;


 A constructor that accepts two arguments, x and y, that initialize the corresponding attributes.
These arguments should have default value of 0.0;
 A method distance_to_origin() that returns the distance from the point to the origin. The formula
for that is x2+y2.
 A method reflect(), that reflects the point with respect to the x- or y-axis:
o accepts one argument axis,
o if axis="x" , it sets the y (not a typo!) attribute to the negative value of the y attribute,
o if axis="y", it sets the x attribute to the negative value of the x attribute,
o for any other value of axis, prints an error

message.

Note: You can choose to use sqrt() function from either the numpy or the math package, but whichever
package you choose, don't forget to import it before starting the class definition!

To check your work, you should be able to run the following code without errors:

pt = Point(x=3.0)
pt.reflect("y")
print((pt.x, pt.y))
pt.y = 4.0
print(pt.distance_to_origin())
and return the output

(-3.0,0.0)
5.0
Answer:

28. Instance and Class data

Encapsulation: building of data and methods

Polymorphism: creating a unified interface


Here MIN_SALARY is class attribute (else self.name, self.salary etc are instance attribute). Why use class
attribute?

 Min/max values for attributes


 Global constants related to the class

Class methods can also possible, although they have a limited scope of usage. Here is shown how to write
if needed. Class methods can’t use instance level data:

The main usage is alternative constructor. For example, we might want to create an Employee object from
data stored in a file. We cannot use a method, because it would require an instance, and there isn’t one
yet. Here we introduced a class method from file that accept a file name, reads the first line from file, that
presumably contains the name of the employee and returns an object instance. In the return statement
we use cls variable that refers to the class. this line cause the init constructor

Then we can call the method from_file by using class dot method syntax.

Above only one argument is initialed i.e. employee name. Here for our employee class the following is
done so it takes same number of argument as before. Now this code works same from console input or
file input. Data in file must written in different lines not with space:

Call for file input:


Call for console input:

29. Exercise
In prev. Player Class another class attribute MAX_SPEED is assigned to 3. Then the following code run:
Same code above, just change: p1.MAX_SPEED = 7 to Player.MAX_SPEED = 7 so the output becomes:

30. Exercise: Class BetterDate


(above + bellow exercise in one code bellow)
31. (Extra)

Make Dictionary assessment

Pass an array
32. Class Inheritance

Object oriented programming is fundamentally about code reuse. Modules like numpy or pandas are a
great tool to use code written by other programmers.

Consider the following class:

Parent class have a method, child class also have the same method but slightly different. If both method
with the same name define in these two class, then same call produce different output basic on the class
of the instance. This is using common interface hence this is an application of polymorphism.
Quiz

Which of the following statements about inheritance of class attributes is correct?

a) Class attributes CANNOT be inherited, but new class attributes of the same name CAN be created
in a child class.
b) Class attributes CANNOT be inherited, and new class attributes of the same name CANNOT be
created in a child class.
c) Class attributes CAN be inherited, and the value of class attributes CAN be overwritten in the child
class
d) Class attributes can be inherited, and the value of class attributes CANNOT be overwritten in the
child class

Ans: c

33. Exercise: Class LoggedDF


https://www.hylkerozema.nl/2021/05/10/creating-a-subclass/

34. Operator Overloading Comparison

Comparing variables cst1, cst2 we are actually comparing references, not the data. (reference to the
memory which are different for different instance).

Incase of array and many other cases, this is true when two things are equal. So how to enforce this in
class? Just overload the equal operator:

Name+ salary can be match but id have to be unique.

Example 2:

A bank account number have to be unique. In a BankAccount class there is an operator overloading that
checks if two accounts have same a/c numbers. Returns true if matches. Now another class Phone have
the same overloading that checks if two numbers are equal. Imagine Bank Account and Phone number is
same. Now if we check if a bank account is a phone number is same, it returns true which is not. So class
types should also be checked. Bellow code:
Another way to ensure that an object has the same type as you expect is to use the isinstance(obj,
Class) function. This can helpful when handling inheritance, as Python considers an object to be an
instance of both the parent and the child class.

Python always calls the child's __eq__() method when comparing a child object to a parent object.

35. Operator overloading: String representation

Suppose cust is an object of Customer class. if you print cust it prints out memory address. Now there are
two special methods that we can define in a class that will return a printable representation of an object:
__str__() and __repr__()
Str() gives an informal representation, suitable for an end user and repr() is mainly used by developers.

The str shouldn’t accept any arguments besides self and it should return a string.

Now define a string representation:

Incase of repr

Following best practices, we make sure that repr returns a string that can be used to reproduce the object,
in this case the exact initialization call.

Official python tutorial doc:

https://docs.python.org/3/library/stdtypes.html#str.format

36. (Extra: Assesment)

In this exercise, consider the following code


my_num = 5
my_str = "Hello"

f = ...
print(f)
where the definition for f is missing.

Here are a few possible variants for the definition of f:


1. f = "my_num is {0}, and my_str is {1}.".format(my_num, my_str)

2. f = "my_num is {}, and my_str is \"{}\".".format(my_num, my_str)

3. f = "my_num is {n}, and my_str is '{s}'.".format(n=my_num, s=my_str)

4. f = "my_num is {my_num}, and my_str is '{my_str}'.".format()

Pick the definition of f that will make the code above print exactly the following:
my_num is 5, and my_str is "Hello".
Ans: 2

You should always define at least one of the string representation methods (__str__(), __repr__()) for
your object to make sure that the person using your class can get important information about the object
easily.

37. Error Handling

Custom exceptions:

 Inherit from Exception or one of its subclasses


 Usually an empty class: example bellow

So the instance will not created at all instead of creating with zero balance despite the error.

(Extra Note) Data Struct in Python:

my_list = ['foo', 4, 5, 'bar', 0.4] ---> List

set_of_base10_numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0} ---> Set


tup1 = ('physics', 'chemistry', 1997, 2000); ---> Tuple

dict1 = {'color': 'blue', 'shape': 'square', 'volume':40} ---> Dictionary

38. Exercise: function invert_at_index


if you raise an exception inside an if statement, you don't need to add an else branch to run the rest of
the code. Because raise terminates the function, the code after raise will only be executed if an exception
did not occur.

Important quiz:

Here in Employee class, if bonus is greater than MAX_BONUS which is 5000 then, BonusError is occurred.
BonusError was inherited from SalaryError. Now in the following code a BonusError is occurred:

Also it is BonusError, but only SalaryError is handling here. But this will still handle BonusError as
‘except block for a parent exception will catch child exceptions’ SalaryError is parent of BonusError.

Result ‘SalaryError caught’

Because a BonusError is also a SalaryError. So It's better to include an except block for a child exception
before the block for a parent exception, otherwise the child exceptions will be always be caught in the
parent block, and the except block for the child will never be executed.
39. Polymorphism

Different class with same method differently work. Then have a common interface to call them without
knowing which method to call. They object type dynamically select appropriate method. This is
polymorphism

Liskov Substitution principle: Base class should be interchangeable with any of its subclasses without
altering any properties of the program.

Violation of LSP:

 (Syntactic incompatibility) Consider our BankAccount+ CheckingAccount class:


BankAccount.withdraw() requires 1 parameter but CheckingAccount.withdraw() requires 2
parameters. (Then we couldn’t use the subclass’s withdraw in place of parent’s, But if the subclass
method have a default value for the second parameter, then there is no problem)
 (Subclass strengthening input condition) Both classes withdraw method require amount
parameter. But BankAccount.withdraw() accept any amount, but CheckingAccount.withdraw()
assumes that the amount is limited (then sometimes the subclass method could not be used in
place of base class, if those unsuitable amount are used)
 Changing additional attributes in subclass’s method
 Changing additional exceptions in subclass’s method.

The ultimate rule is that if your class hierarchy violates the Lickov substitution principle, then you should
not be using inheritance, because it is likely to cause the code to behave in unpredictable ways somewhere
down the road.

Circle Ellipse Problem: a famous software design process that shows how our notions of inheritance are
flawed.

40. Exercise: Circle-Ellipse Problem


What went wrong with these classes?

a) This wasn't a correct use of inheritance: we did not call the parent constructor in the child
constructor.
b) We cannot set the h attribute to 7 in the Square object because it will cause an error.
c) The 4x4 Square object would no longer be a square if we assign 7 to h.
d) Because a Square only has one side length, it should not have the h attribute. We should not have
included the h attribute in the constructor.
e) All of the above.

Ans: c
How does using these setter methods violate Liskov Substitution principle?

a) There are syntactic inconsistencies.


b) Each of the setter methods of Square change both h and w attributes, while setter methods
of Rectangle change only one attribute at a time, so the Square objects cannot be substituted
for Rectangle into programs that rely on one attribute staying constant
c) The setter methods of Square accept only limited range of parameters, unlike the setter methods
of Rectangle, so the Square objects cannot be substituted for Rectangle into programs that use
parameter values outside that range
d) All of the above

Ans: b

41. Managing Data access: private attributes

All class data in python is public. But there are a few ways to manage access to data.

 Naming convention:
 Use @properties to customize access
 Overriding __getattr__() and __setattr__()

Naming convention: starts with a single _ : isn’t consider a part of classes public interface

Starts but doesn’t end with __ -> private, so it can be prevented to get overriding

Exercise: Drag and Drop:


42. Exercise: Class BetterDate p-2
43. Properties

Recall Employee class, in that class salary is an important attribute, but directly from object, salary can set
to any value, string, negative number etc.

Restricted and read only attribute: In pandas dataframe, column name can be changed:

But this will cause error if we try to add 3 columns to df

We can use the similar behavior using the property decorator. Use “protected” attribute with leading _
to store salary.
Why properties are useful?

The user of the class will not have to do anything special, They won’t even be able to distinguish between
properties and regular attributes. You on the other hand have some control over the access.

 If you do not use setter method the property will be read only,
 Add @att.getter method to retrieve the property value.
 Add @att.deleter: use for the method that is called when the property is deleted using del

What do properties do?

You could think of properties as attributes with built-in access control. They are especially useful when
there is some additional code you'd like to execute when assigning values to attributes.

Which of the following statements is NOT TRUE about properties?

a) Properties can be used to implement "read-only" attributes


b) Properties can prevent creation of new attributes via assignment
c) Properties can prevent creation of new attributes via assignment
d) Properties allow for validation of values that are assigned to them

Ans: b

44. Exercise class Customer


Now the user of your Customer class won't be able to assign arbitrary values to the customers' balance.
You could also add a custom getter method (with a decorator @balance.getter) that returns a value and
gets executed every time the attribute is accessed.
Similarly, from previous LoggedDF function implemented a variable called, created_at that assign the
current date-time. But that attribute can set to anything by user. We need to make it read only, so modify
the code as following: 1. Instead of created_at, we use _created_at. 2. Then apply @property with no
setter method

You might also like