CS50P 8_Object-Oriented Programming

Object-Oriented Programming (OOP) 

Class ( 類別 )

Object ( 物件)

Attribute ( 屬性 )

Method ( 方法)

Constructor ( 建構子 )

Class

Class provides a way to bundle data and functionality together, creating a new class also creates a new type of object, which allows for the creation of new instances of that type.

Class 提供了一種結合資料與功能的手段。建立一個 class 將會新增一個物件的型別,並且允許建立該型別的新實例

Class Description

An abstract concept - cars, humans, elephants, cakes ...

Cars are vehicles can move.

Humans are primate can think.

Elephants are big animals can walk.

Cakes are food that can be sold.

Class  -- Car

  • It has a brand, price, power source, and license plate number.

  • Inherently powered by a motor and wheels, it moves forward.

  • It can have features like cruise control and lane-keeping assist.

Attribute  - static data

Method - action operation

Class definition

class ClassName:
    ...
    ...

Object instantiation

object = ClassName()

How to Use the Class

Class Example - Car

# Define a car Class
class Car:
    pass # nothing to do

car1 = Car() # Car instance / car object
car2 = Car() # Car instance / car object

Instance Variable

Each instance has its own attribute

# Define a car Class
class Car:
    pass # nothing to do
  
car1 = Car() # Car instance / car object
car1.brand = "Toyota"

car2 = Car() # Car instance / car object
car2.weight = 450

__init__() Special Method

Create default instance variables.

init(self [,... ]): constructor self is the instance itself

#initial the instace variable withr default value
def __init__(self):
    self.attribute = "default value"

#initial the instace variable with user defined value
def __init__(self, attr1):
    self.attribute = attr

Define the Car Class and Default Instance Variables

# Define a car Class
class Car:
    # Special Metho, Constructor
    def __init__(self):
        # initial instance variable
        self.brand = "Toyota"

Define the Car Class and Default Instance Variables

Creating Object: Car Class with Default Instance Variables

class Car:
    # Constructor
    def __init__(self):
        # initial instance variable
        self.brand = "Toyota"

car1 = Car()

Creating Object: Car Class with Default Instance Variables

Creating Objects: Car Class with initial Instance Variables

class Car: 
    def __init__(self, brand):
        self.brand = brand

car1 = Car("Toyota")
car2 = Car("Tesla")

Creating Objects: Car Class with Initial Instance Variables

Object Access Attribute

object.attribute_name

class Car:
    def __init__(self, brand):
        self.brand = brand
        
car1 = Car("Tesla")
# print car brand
print(f"car1.brand is {car1.brand}")
car1.brand is Tesla

Default Initial Values for __init__()

class Car:
    # sepacial method with default Toyota brand   
    def __init__(self, brand = "Toyota"):
        # initial instance variable brand
        self.brand = brand
        
car1 = Car() # No brand --> brand is Toyota
print(f"car1.brandis {car1.brand}")
car1.brand is Toyota

Create Objects with Default Initial Values

class Car:  
    # sepacial method with default Toyota brand   
    def __init__(self, brand = "Toyota"):
        # initial instance variable brand
        self.brand = brand

car1 = Car("Tesla") # brand is Tesla
print(f"car1.brand is {car1.brand}")
car1.brand is Tesla

Initial Values for __init__()

Create Objects with Initial Values

Instance Methods

The methods in the class do not have any decorators.

Class ClassName:
    def method(self[,...]):
        ...
        ...

Car Class with Instance Methods

class Car:  
    def __init__(self, brand = "Toyota"):
        self.brand = brand

    # instance method    
    def info(self):
        return f"This car is {self.brand} brand)"

Access instance method

object.method_name

class Car:  
    def __init__(self, brand = "Toyota"):
        self.brand = brand 
    def info(self):
        return f"The brand of the car is {self.brand}"

car1 = Car("Tesla")
print(car1.info())
The brand of the car is Tesla

Access instance method

Class Variable

Variables in class are shared by all instances.
Class ClassName:
    attribute = xxx
    ...
    ...

Car Class with Class Variable

class Car:
    chinese_name = "汽車" # 類別變數 class variable
    def __init__(self, brand = "Toyota"):
        self.brand = brand 
    def info(self):
        return f"This {self.brand} is {self.chinese_name}"
car1 = Car("Tesla")
print(car1.info())
car2 = Car("Toyota")
print(car2.info())
This Tesla is 汽車
This Toyota is 汽車

Both cars, chinese_name, are the same!!!

Car Class with Class Variable

special method str(self)

Default method for Class, object's string representation
class Car:
    status = "Good" # class attribute
    def __init__(self, brand = "Toyota"):
        self.brand = brand
    def __str__(self):
        return f"Car class status {self.status} from __str__"
    def info(self):
        return f"This {self.brand} is {self.status}"

car1 = Car("Tesla")
print(car1)
Car class status Good from __str__
print(object) --> python call object.__str__(self)

special method str(self)

Class Method

In the class, there is a method decorated with @classmethod. When calling the class method, the cls parameter is passed, which refers to the class.

class ClassName:
    # Class Method
    @classmethod
    def class_metho(cls):
        ...
        ...

Car Class with Class Method

class Car:
    status = "Good" # class attribute
    # 類別方法(Class Method)
    @classmethod
    def chk_status(cls):
        print("Car chk_staus is {cls.status}.")

Car.chk_status()
Car chk_staus is Good.

Accessing Instance Variables

The attribute for the car's engine number.

class Car:
    def __init__(self, engin_no = "0000-0000"):
        self.engin_no = engin_no
    def __str__(self):
        return f"Car's engin_no is  {self.engin_no}"

car1 = Car("1234-5678")
print(car1)
car1.engin_no = "2468-1357"
print(car1)
Car's engin_no is  1234-5678
Car's engin_no is  2468-1357

Engine numbers can be changed!!!

Accessing Instance Variables

Access of Instance Variables with @property

The @property decorator transforms a method into a read-only variable.
class Car:
    def __init__(self, engin_no = "0000-0000"):
        self._engin_no = engin_no
    @property # engin_no just can be read
    def engin_no(self):
        return self._engin_no
car1 = Car("1234-5678")
print(f"car1.engin_no {car1.engin_no}")
car1.engin_no = "2468-1357"
car1.engin_no 1234-5678
---------------------------------
AttributeError    Traceback (most recent call last)
<ipython-input-3-dd4183959b5d> in <module>
      7 car1 = Car("1234-5678")
      8 print(f"car1.engin_no {car1.engin_no}")
----> 9 car1.engin_no = "2468-1357"

AttributeError: can't set attribute

Modifying Instance Variables with @property

@property instance_variable.setter

class Car:
    def __init__(self, engin_no = "0000-0000"):
        self._engin_no = engin_no
    @property # engin_no just can be read
    def engin_no(self):
        return self._engin_no
    @engin_no.setter
    def engin_no(self, engin_no):
        self._engin_no = engin_no
    
car1 = Car("1234-5678")
print(f"car1.engin_no {car1.engin_no}")
car1.engin_no = "2468-1357"
print(f"car1.engin_no {car1.engin_no}")
car1.engin_no 1234-5678
car1.engin_no 2468-1357

Modifying Instance Variables with @property

 Inheritance

If you inherit money or property, you receive it from someone who has died. 繼承

If you inherit a characteristic or quality, you are born with it, because your parents or ancestors also had it. 遺傳

Python Class Inheritance

Inheritance allows classes to have common attributes or methods.

Child class inherits common attributes or methods from parent class.

Two Class of Cars

class gasoline_Car:
    def __init__(self, brand, engin):
       self.brand = brand
       self.engin = engin

class electric_Car:
    def __init__(self, brand, battery):
       self.brand = brand
       self.battery = battery

gcar = gasoline_Car("Totyo", "Turbo")
ecar = electric_Car("Tesla", "750kw")

Brand is the same attribute...

Car - Parent Class of Vehicle Class

The common attribute of cars - brand.

class car:
    def __init__(self, brand):
       self.brand = brand
    
car = car("Toyota")

Class Inheritance

class child_class(parent_class):
    #super() is parent class
    ...

The gasoline_Car class inherits from the car class

class car:
    def __init__(self, brand):
       self.brand = brand
    
class gasoline_Car(car):
    def __init__(self, brand, engin):
       super().__init__(brand)
       self.engin = engin
        
gcar = gasoline_Car("Totyo", "Turbo") 

The gasoline_Car class inherits from the car class

Two Car Classes Inheritance

class car:
    def __init__(self, brand):
       self.brand = brand     
class gasoline_Car(car):
    def __init__(self, brand, engin):
       super().__init__(brand)
       self.engin = engin
class electric_Car(car):
    def __init__(self, brand, battery):
       super().__init__(brand)
       self.battery = battery
      
gcar = gasoline_Car("Totyo", "Turbo")
ecar = electric_Car("Tesla", "750kw")

Two common attributes in inheritance class

class car:
    def __init__(self, brand, engin_no):
       self.brand = brand
       self.engin_no = engin_no
    
class gasoline_Car(car):
    def __init__(self, brand, engin_no, engin):
       super().__init__(brand, engin_no)
       self.engin = engin
        
gcar = gasoline_Car("Totyo", "12345678", "Turbo") 

Operator overloading

 Operator   Method
+ object.__add__(self, other)
- object.__sub__(self, other)
* object.__mul__(self, other)
// object.__floordiv__(self, other)
/  object.__div__(self, other)
% object.__mod__(self, other)

__add__() example

class MyTime:
    def __init__(self, h=0, m=0):
        self.hour = h
        self.min = m
    def __add__(self, other):
        nhour = self.hour+other.hour
        nmin  = self.min+other.min
        if nmin >= 60:
            nhour = nhour + 1
            nmin  -= 60
        if nhour >= 24:
            nhour -= 24
        return MyTime(nhour, nmin) 
    def __str__(self):
        return f"{self.hour:02} : {self.min:02}"
        
time1 = MyTime(22, 40)
time2 = MyTime(2, 30)
time3 = time1 + time2
print(f"{time1} + {time2} = {time3}")
22 : 40 + 02 : 30 = 01 : 10
Made with Slides.com