01-Object Oriented Programming (1) - Jupyter Notebook
01-Object Oriented Programming (1) - Jupyter Notebook
(https://www.udemy.com/user/joseportilla/)
There are many, many tutorials and lessons covering OOP so feel free to Google search
other lessons, and I have also put some links to other useful tutorials online at the bottom of
this Notebook.
For this lesson we will construct our knowledge of OOP in Python by building on the
following topics:
Objects
Using the class keyword
Creating class attributes
Creating methods in a class
Learning about Inheritance
Learning about Polymorphism
Learning about Special Methods for classes
Lets start the lesson by remembering about the Basic Python Objects. For example:
In [2]: lst.count(2)
Out[2]: 1
What we will basically be doing in this lecture is exploring how we could create an Object
type like a list. We've already learned about how to create functions. So let's explore Objects
in general:
Objects
In Python, everything is an object. Remember from previous lectures we can use type() to
check the type of object something is:
In [3]: print(type(1))
print(type([]))
print(type(()))
print(type({}))
<class 'int'>
<class 'list'>
<class 'tuple'>
<class 'dict'>
So we know all these things are objects, so how can we create our own Object types? That
is where the class keyword comes in.
class
User defined objects are created using the class keyword. The class is a blueprint that
defines the nature of a future object. From classes we can construct instances. An instance
is a specific object created from a particular class. For example, above we created the
object lst which was an instance of a list object.
<class '__main__.Sample'>
By convention we give classes a name that starts with a capital letter. Note how x is now
the reference to our new instance of a Sample class. In other words, we instantiate the
Sample class.
Inside of the class we currently just have pass. But we can define class attributes and
methods.
For example, we can create a class called Dog. An attribute of a dog may be its breed or its
name, while a method of a dog may be defined by a .bark() method which returns a sound.
Attributes
The syntax for creating an attribute is:
self.attribute = something
__init__()
sam = Dog(breed='Lab')
frank = Dog(breed='Huskie')
__init__()
Each attribute in a class definition begins with a reference to the instance object. It is by
convention named self. The breed is the argument. The value is passed during the class
instantiation.
self.breed = breed
Now we have created two instances of the Dog class. With two breed types, we can then
access these attributes like this:
In [6]: sam.breed
Out[6]: 'Lab'
In [7]: frank.breed
Out[7]: 'Huskie'
Note how we don't have any parentheses after breed; this is because it is an attribute and
doesn't take any arguments.
In Python there are also class object attributes. These Class Object Attributes are the same
for any instance of the class. For example, we could create the attribute species for the Dog
class. Dogs, regardless of their breed, name, or other attributes, will always be mammals.
We apply this logic in the following manner:
def __init__(self,breed,name):
self.breed = breed
self.name = name
In [10]: sam.name
Out[10]: 'Sam'
Note that the Class Object Attribute is defined outside of any methods in the class. Also by
convention, we place them first before the init.
In [11]: sam.species
Out[11]: 'mammal'
Methods
Methods are functions defined inside the body of a class. They are used to perform
operations with the attributes of our objects. Methods are a key concept of the OOP
paradigm. They are essential to dividing responsibilities in programming, especially in large
applications.
You can basically think of methods as functions acting on an Object that take the Object
itself into account through its self argument.
Radius is: 1
Area is: 3.14
Circumference is: 6.28
In the _init_ method above, in order to calculate the area attribute, we had to call Circle.pi.
This is because the object does not yet have its own .pi attribute, so we call the Class Object
Attribute pi instead.
In the setRadius method, however, we'll be working with an existing Circle object that does
have its own pi attribute. Here we can use either Circle.pi or self.pi.
Now let's change the radius and see how that affects our Circle object:
In [13]: c.setRadius(2)
print('Radius is: ',c.radius)
print('Area is: ',c.area)
print('Circumference is: ',c.getCircumference())
Radius is: 2
Area is: 12.56
Circumference is: 12.56
Great! Notice how we used self. notation to reference attributes of the class within the
method calls. Review how the code above works and try creating your own method.
Inheritance
Inheritance is a way to form new classes using classes that have already been defined. The
newly formed classes are called derived classes, the classes that we derive from are called
base classes. Important benefits of inheritance are code reuse and reduction of complexity
of a program. The derived classes (descendants) override or extend the functionality of base
classes (ancestors).
localhost:8888/notebooks/Documents/Python - assignment/01-Object Oriented Programming (1).ipynb 5/9
7/11/24, 12:57 PM 01-Object Oriented Programming (1) - Jupyter Notebook
Let's see an example by incorporating our previous work on the Dog class:
In [15]: d = Dog()
Animal created
Dog created
In [16]: d.whoAmI()
Dog
In [17]: d.eat()
Eating
In [18]: d.bark()
Woof!
In this example, we have two classes: Animal and Dog. The Animal is the base class, the
Dog is the derived class.
Finally, the derived class extends the functionality of the base class, by defining a new bark()
method.
Polymorphism
We've learned that while functions can take in different arguments, methods belong to the
objects they act on. In Python, polymorphism refers to the way in which different object
classes can share the same method name, and those methods can be called from the same
place even though a variety of different objects might be passed in. The best way to explain
this is by example:
class Cat:
def __init__(self, name):
self.name = name
def speak(self):
return self.name+' says Meow!'
niko = Dog('Niko')
felix = Cat('Felix')
print(niko.speak())
print(felix.speak())
Here we have a Dog class and a Cat class, and each has a .speak() method. When
called, each object's .speak() method returns a result unique to the object.
There a few different ways to demonstrate polymorphism. First, with a for loop:
In both cases we were able to pass in different object types, and we obtained object-specific
results from the same mechanism.
localhost:8888/notebooks/Documents/Python - assignment/01-Object Oriented Programming (1).ipynb 7/9
7/11/24, 12:57 PM 01-Object Oriented Programming (1) - Jupyter Notebook
A more common practice is to use abstract classes and inheritance. An abstract class is one
that never expects to be instantiated. For example, we will never have an Animal object, only
Dog and Cat objects, although Dogs and Cats are derived from Animals:
def speak(self):
return self.name+' says Woof!'
class Cat(Animal):
def speak(self):
return self.name+' says Meow!'
fido = Dog('Fido')
isis = Cat('Isis')
print(fido.speak())
print(isis.speak())
opening different file types - different tools are needed to display Word, pdf and Excel
files
adding different objects - the + operator performs arithmetic and concatenation
Special Methods
Finally let's go over special methods. Classes in Python can implement certain operations
with special method names. These methods are not actually called directly but by Python
specific language syntax. For example let's create a Book class:
A book is created
Title: Python Rocks!, author: Jose Portilla, pages: 159
159
A book is destroyed
These special methods are defined by their use of underscores. They allow us to use Python
specific functions on objects created through our class.
Great! After this lecture you should have a basic understanding of how to create your
own objects with class in Python. You will be utilizing this heavily in your next
milestone project!