Object Oriented Programming in Python
In normal life to tend to think in sequences of activities.
- Code as a sequence of steps
- Great for data analysis and scripts
- Code as interactions of objects
- Great for building framework and tools
- Maintainable and reusable code!
Objects as datastructures
Object = state + behavior
Encapsulation – bundling data with code operating on it
A Class can be seen as a blueprint for objects defining states and behaviours.
Objects in Python
- Everything in Python is an object
- Every object has a class
- Use type() to find the class
import numpy as np a = np.array([1, 2, 3, 4,]) print(type(a))
Attributes and methods
State <-> attributes
import numpy as np a = np.array([1, 2, 3, 4]) # shape attribute a.shape
Behaviour <-> methods
import numpy as np a = np.array([1, 2, 3, 4]) # reshape method a.reshape(2,2)
array([[1, 2], [3, 4]])
obj.to access attributes and methods
Object = attributes + methods
- attributes <-> variables <->
- method <-> function() <->
import numpy as np a - np.array([1, 2, 3, 4]) dir(a) # <--- list all attributes and methods
['T', '__abs__', ... 'trace', 'transpose', 'var', 'view']
A basic class
class Customer: # code for class goes here pass
class <name>:starts a class definition
- code inside
passto create an “empty” class
c1 = Customer() c2 = Customer()
ClassName()to creatie an object of class
Adding methods to a class
class Customer: def identify(self, name): print("I am Customer " name)
- method definition – function definition within class
- use self as the 1st argument in method definition
cust = Customer() cust.identify("Hylke")
I am Customer Hylke
selfwhen calling method on an object
class Customer: def identify(self, name): print("I am Customer " + name) cust = Customer() cust.identify("Hylke")
What is self?
- classes are templates, how to refer data of a particular object?
selfis a stand-in for a particular object used in class definition
- should be the first argument of any method
- Python will take care of
selfwhen methods called for an object:
cust.identify("Laura")will be interpreted as
How to create attributes
- Encapsulation : bundling data with methods that operate on data
Customer‘s’ name should be an attribute
Attributes are created by assignment (=) in methods
Adding an attribute to a class
class Customer: # set the name attribute of an object to new_name def set_name(self, new_name): # Create an attribute by assigning a value self.name = new_name # <--- will create .name when set_name is called cust - Customer() # <--- .name doesn't exist here yet cust.set_name("Hylke Rozema") # <--- .name is created and set to "Hylke Rozema" print(cust.name) # <--- .name can be used
class Customer: # Using a parameter def identify(self, name): print("I am Customer" + name) cust = Customer() cust.identify("Mark Carr")
I am Customer Mark Carr
class Customer: def set_name(self, new_name): self.name = new_name # Using .name from the object it*self* def identify(self): print("I am Customer" + self.name) cust = Customer() cust.set_name("Mary Dillan") cust.identify()
I am Customer Mary Dillan
The __init__ constructor
- Methods are function definitions within a class
selfas the first argument
- Define attributes by assignment
- Refer to attributes aan class via
class MyClass: # function definition in class # first argument is self def my_method1(self, other_args...): # do things here def my_method2(self, my_attr): # attribute created by assignment self.my_attr = my_attr ...
Constructor __init__() method
- Add data to object when creating it?
__init__()method is called every time an object is created
class Customer: def __init__(self, name): self.name = name # <--- Create the .name attribute and set it to name parameter print("The __init__ method was called") cust = Customer("Hylke Rozema") # <--- __init__ is implicitly called print(cust.name)
The __init__ method was called Hylke Rozema
class Customer: def __init__(self, name, balance): # <-- balance parameter added self.name = name self.balance = balance # <-- balance attribute added print("The __init__ method was called") cust = Customer("Hylke Rozema", 1000) # <-- __init__ is called print(cust.name) print(cust.balance)
The __init__ method was called Hylke Rozema 1000
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.
Define the class
Point that has:
- Two attributes,
y– the coordinates of the point on the plane;
- A constructor that accepts two arguments,
y, that initialize the corresponding attributes. These arguments should have default value of
- 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:
- accepts one argument
axis="x", it sets the
y(not a typo!) attribute to the negative value of the
axis="y", it sets the
xattribute to the negative value of the
- for any other value of
axis, prints an error message.
- accepts one argument
Note: You can choose to use
sqrt() function from either the
numpy or the
mathpackage, 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
from numpy import sqrt # Write the class Point as outlined in the instructions class Point: def __init__(self, x=0.0, y=0.0): self.x = x self.y = y def distance_to_origin(self): return sqrt(self.x**2 + self.y**2) def reflect(self, axis): if axis=="x": self.y=-self.y elif axis=="y": self.x=-self.x else: print("Error") pt = Point(x=3.0) pt.reflect("y") print((pt.x, pt.y)) pt.y = 4.0 print(pt.distance_to_origin())
Notice how you implemented
distance_to_origin() as a method instead of an attribute. Implementing it as an attribute would be less sustainable – you would have to recalculate it every time you change the values of the
y attributes to make sure the object state stays current.