先前的課程教過type()
函式,
可以回傳指定物件的型態
但你有認真看那個"型態"是甚麼嗎?
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 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"
有的時候你會需要不同的複雜資料結構彼此幫忙
以"課程"跟"學生"為例
# 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)
想像你想要寫\(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}')
優點:
dog1_name = "Sam" dog1_age = 16 ... # 如果需要一堆狗,你就會要打一堆有關的變數,出錯機率就會提高 dogs_name = ["Sam", "Apollo", ...] dogs_age = [16, 16, ...] #這種方法在刪除跟新增資料時會格外麻煩,還要特別花時間找到對的index