changed 3 years ago
Linked with GitHub

Python

實作前導課程:class & object Part I

2022 / 4 / 15

Tony


其實你已經看過class了?!


先前的課程教過type()函式,
可以回傳指定物件的型態
但你有認真看那個"型態"是甚麼嗎?

Example
x = 10 name = "Tony" def Say_Hi(): print("Hi") print(type(x)) #<class 'int'> print(type(name)) #<class 'str'> print(type(Say_Hi)) #<class 'function'>

他們的資料型態前面都有一個class,代表
int, str等等的資料型態其實都是不同的class(類別)
而這些值、變數則都是那些Class的物件(object)


有時候我們會需要更複雜,但是Python沒有內建的資料結構
這個時候就要自己寫一個class出來

class Dog class Students class Course ...

寫寫看簡單的class


我們可以寫一個簡單的class來玩玩看

class Dog: def __init__(self, name , age , color): pass def speak(self): print('Bark')

__init__函式:有這個class的物件被創造的時候會自動執行的函式

class裡面的函式,多數時候第一個引數都會是self,代表執行該函式的物件

def __init__(self, name, age, color): self.name = name self.age = age self.color = color

宣告物件並跟函式互動

Sam = Dog("Sam", 16, "Black") Sam.speak() # "Bark"

class之間的互動


有的時候你會需要不同的複雜資料結構彼此幫忙
以"課程"跟"學生"為例

模板
# Multiple classes interaction class Student: def __init__(self, name, age, grade): self.name = name self.age = age self.grade = grade # 0 ~ 100 def get_grade(self): return self.grade class Course: def __init__(self, name, max_students): pass def add_student(self, student): pass def get_average_grade(self): pass if __name__ == '__main__': s1 = Student('Tim', 16, 90) s2 = Student('Tony', 17, 85) s3 = Student('Max', 20, 65) course = Course('Physics', 2) course.add_student(s1) course.add_student(s2) print(course.students) print(course.students[0].name) print(course.get_average_grade())

__init__:
設定課程名稱、學生上限、參加的學生(用一個list儲存)

def __init__(self, name, max_students): self.name = name self.max_students = max_students self.students = [] # We can create an attribute that is not one of the parameters.

add_student():
還沒滿人時,把要參加的學生加進課程裡面

def add_student(self, student): if len(self.students) < self.max_students: self.students.append(student) return True return False

get_average_grade():
算出學生們的平均分數

def get_average_grade(self): value = 0 for student in self.students: value += student.get_grade() return value / len(self.students)

完整Code

# Multiple classes interaction class Student: def __init__(self, name, age, grade): self.name = name self.age = age self.grade = grade # 0 ~ 100 def get_grade(self): return self.grade class Course: def __init__(self, name, max_students): self.name = name self.max_students = max_students self.students = [] # We can create an attribute that is not one of the parameters. def add_student(self, student): if len(self.students) < self.max_students: self.students.append(student) return True return False def get_average_grade(self): value = 0 for student in self.students: value += student.get_grade() return value / len(self.students)

繼承 Inheritance


想像你想要寫\(n\)個class,分別代表\(n\)種課程
它們都有名稱、短介紹、開課人數
其中有\(k\)種課程要收費,\(m\)種課程只開放半年
想想看要怎麼寫?


你可以一個一個像這樣:

class AI_Crash_Course: def __init__(self, intro, max_student, date, tuition_fee): self.intro = intro self.max_student = max_student self.date = date self.tuition_fee = tuition_fee def get_grade(self): ... #以下忽略N行

但是這樣太慢了,而且太多行了,好複雜
有沒有更方便的寫法?


繼承:讓一個子類別(Chind_clsss)可以使用母類別(Parent_class)所有的函式,但不用全部寫出來
並且接受子類別自己重新調整、更新母類別寫過的函式


舉例:我要寫兩個class分別代表狗跟貓
他們都有名字、年紀、顏色,也都會叫
所以我先寫一個寵物class讓他們繼承

class Pet: def __init__(self, name, age, color): self.name = name self.age = age self.color = color

繼承的寫法:把Parent_class寫在Child_class的名稱後面,用小括號包起來

class Dog(Pet): pass class Cat(Dog): pass

使用Parent_class的函式:super()
super()代表現在這個class的Parent_class

class Dog(Pet): def __init__(self, name, age, color): super().__init__(name, age, color) def speak(self): print(f'I am {self.name} and I am {self.age} years old and I am {self.color}') class Cat(Pet): def __init__(self, name, age, color): super().__init__(name, age, color) def speak(self): print(f'I am {self.name} and I am {self.age} years old and I am {self.color}')

為什麼要學class?


優點:

  • 方便處理"同一個東西有很多屬性"的專案
  • 可以分類函式、讓程式語言變得更一目了然
dog1_name = "Sam" dog1_age = 16 ... # 如果需要一堆狗,你就會要打一堆有關的變數,出錯機率就會提高 dogs_name = ["Sam", "Apollo", ...] dogs_age = [16, 16, ...] #這種方法在刪除跟新增資料時會格外麻煩,還要特別花時間找到對的index
Select a repo