# Python
## 實作前導課程:class & object Part I
### 2022 / 4 / 15
### Tony
---
## 其實你已經看過class了?!
----
先前的課程教過`type()`函式,
可以回傳指定物件的型態
但你有認真看那個"型態"是甚麼嗎?
:::spoiler Example
```python=
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出來
```python=
class Dog
class Students
class Course
...
```
---
## 寫寫看簡單的class
----
我們可以寫一個簡單的class來玩玩看
```python=
class Dog:
def __init__(self, name , age , color):
pass
def speak(self):
print('Bark')
```
----
\_\_init__函式:有這個class的物件被創造的時候會自動執行的函式
class裡面的函式,多數時候第一個引數都會是<font color = 'orange'>`self`</font>,代表執行該函式的物件
```python=
def __init__(self, name, age, color):
self.name = name
self.age = age
self.color = color
```
----
宣告物件並跟函式互動
```python=
Sam = Dog("Sam", 16, "Black")
Sam.speak() # "Bark"
```
---
## class之間的互動
----
有的時候你會需要不同的複雜資料結構彼此幫忙
以"課程"跟"學生"為例
:::spoiler 模板
```python=
# 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儲存)
```python=
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():
還沒滿人時,把要參加的學生加進課程裡面
```python=
def add_student(self, student):
if len(self.students) < self.max_students:
self.students.append(student)
return True
return False
```
----
get_average_grade():
算出學生們的平均分數
```python=
def get_average_grade(self):
value = 0
for student in self.students:
value += student.get_grade()
return value / len(self.students)
```
----
完整Code
```python=
# 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$種課程只開放半年
想想看要怎麼寫?
----
你可以一個一個像這樣:
```python=
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讓他們繼承
```python=
class Pet:
def __init__(self, name, age, color):
self.name = name
self.age = age
self.color = color
```
----
繼承的寫法:把Parent_class寫在Child_class的名稱後面,用小括號包起來
```python=
class Dog(Pet):
pass
class Cat(Dog):
pass
```
----
使用Parent_class的函式:super()
`super()`代表現在這個class的Parent_class
```python=
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?
----
優點:
* 方便處理"同一個東西有很多屬性"的專案
* 可以分類函式、讓程式語言變得更一目了然
```python=
dog1_name = "Sam"
dog1_age = 16
...
# 如果需要一堆狗,你就會要打一堆有關的變數,出錯機率就會提高
dogs_name = ["Sam", "Apollo", ...]
dogs_age = [16, 16, ...]
#這種方法在刪除跟新增資料時會格外麻煩,還要特別花時間找到對的index
```
{"metaMigratedAt":"2023-06-16T23:09:41.107Z","metaMigratedFrom":"YAML","title":"Python實作前導課程:class & object Part I","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"theme\":null}","contributors":"[{\"id\":\"4f731eff-9d88-41f4-af56-2e3e02f20cfc\",\"add\":7683,\"del\":2529}]"}