# Class slide ver.
bearrrrrrro 2020/5/23
sylveon 2021/5/7 修改
---
## 語法
```python
class ClassName:
pass
```
----
加上一些東西
```python
class Computer:
pass
cp_1 = Computer()
cp_1.cpu = 'i5-8750'
cp_1.size = 14
cp_1.price = 20000
cp_2 = Computer()
cp_2.cpu = 'i7-1450'
cp_2.size = 10
cp_2.price = 2000
```
----
試試看
```python
print(cp_1)
print(cp_1.cpu)
print(cp_2.price)
```
---
## 作用

----
* 好懂
* 易讀
* 減少重複性高的程式碼
* 看起來比較專業 XD
----
## 概念
* 可以發揮你的想像力做出幾乎任何東西
* 自定義物件(資料型態?)
* 當你想把某些狀態(資料)和功能(函式)綁在一起時,class是一個好選擇
----
## 一些不知道不影響你打code但是知道比較好的東西
* class 又稱為「類別」
* class 底下的資料又稱為「屬性」
* class 底下的函式又稱為「方法 (method)」
----
### 更多簡單的範例
電腦
```python
class Computer:
def __init__(self, cpu, size, price):
self.cpu = cpu
self.size = size
self.price = price
```
* 其中`__init__`是比較特殊的函式,會在「建構物件」時自動呼叫(後面有範例)
* 這裡的 `xxx.yyy`指"xxx的yyy",有點類似之前在import一些工具中的用法
----
人
```python
class Person:
def __init__(self, name, height, weight):
self.name = name
self.height = height # cm
self.weight = weight # kg
def get_bmi(self):
return self.weight / (self.height / 100) ** 2
```
----
baba
```python
class Baba:
def __init__(self, x, y):
self.x = x
self.y = y
def up(self):
self.x -= 1
def down(self):
self.x += 1
def left(self):
self.y -= 1
def right(self):
self.y += 1
```
----
**Remark:** class中的函式第一個參數要放self,不然可能會噴錯或是發生奇怪的事情(?
----
**Remark:** `__init__`中參數的名稱可以任意,像是我也可以這樣寫
```python
class Animal:
def __init__(self, x):
self.name = x
```
但名稱不一致可能造成混淆而且沒有必要,除了可以少打幾個字以外沒有任何好處

---
## 用class
----
### Instance
Instance 又稱為「實體」,依照class真的某個東西做出來
| Class | Instance |
| -------- | -------- |
| 設計圖 | 真正的東西 |
----
有了class以後,我們可以造出多個狀態和功能類似的東西

----
```python
cp_1 = Computer('i5-8750', 14, 20000)
cp_2 = Computer('i7-1450', 10, 2000)
print(cp_1)
print(cp_1.cpu)
print(cp_2.price)
```
----
```python
bearrrrrrro = Person('bearrrrrrro', 170, 71)
print(bearrrrrrro.name)
print(bearrrrrrro.get_bmi())
```
---
## 連連看

----
[解答](https://i.imgur.com/PPL9Hgg.png)
---
## 練習1
小明不小心把墨水打翻在他的code上,請幫小明通靈被墨水蓋掉的資訊
```python
class Student:
def __init__(self, name, math, english, chinese):
墨墨墨墨墨
墨墨墨墨墨
墨墨墨墨墨
墨墨墨墨墨
def average(墨墨墨墨墨墨
墨墨墨墨墨 # 回傳三科的平均值
def is_pass(墨墨墨墨墨墨
墨墨墨墨墨 # 每一科都不低於60分就回傳true
boss = Student('Sophia', 80, 100, 100)
print(boss.average())
print(boss.is_pass())
```
----
```python
class Student:
def __init__(self, name, math, english, chinese):
self.name = name
self.math = math
self.english = english
self.chinese = chinese
def average(self):
return sum((self.math, self.english, self.chinese)) / 3 # 回傳三科的平均值
def is_pass(self):
return min((self.math, self.english, self.chinese)) >= 60 # 每一科都不低於60分就回傳true
boss = Student('Sophia', 1000, 100, 100)
print(boss.average())
print(boss.is_pass())
```
---
## 特殊方法(補充) + 練習2
```python
from math import gcd
class Rational:
def __init__(self, p, q):
t = gcd(p, q)
p, q = p // t, q // t
self.p = p
self.q = q
def __str__(self):
return '{}/{}'.format(self.p, self.q)
def __add__(self, a):
# print('{} + {}'.format(self, a))
nu = self.p * a.q + a.p * self.q
di = self.q * a.q
com = gcd(nu, di)
return Rational(nu // com, di // com)
# Your part here!!
def __sub__(self, a): # x - y
# print('{} - {}'.format(self, a))
pass
def __mul__(self, a): # x * y
# print('{} * {}'.format(self, a))
pass
def __truediv__(self, a): # x / y
# print('{} / {}'.format(self, a))
pass
def __eq__(self, a): # x == y
# print('{} == {}'.format(self, a))
pass
if __name__ == '__main__':
r = Rational(1, 4)
s = Rational(3, 8)
t = Rational(2, 8)
print(r + s)
print(r - s)
print(r * s)
print(r / s)
print(r == s)
print(r == t)
```
----
解答
```python
from math import gcd
class Rational:
def __init__(self, p, q):
t = gcd(p, q)
p, q = p // t, q // t
self.p = p
self.q = q
def __str__(self):
return '{}/{}'.format(self.p, self.q)
def __add__(self, a):
# print('{} + {}'.format(self, a))
nu = self.p * a.q + a.p * self.q
di = self.q * a.q
com = gcd(nu, di)
return Rational(nu // com, di // com)
# Your part here!!
def __sub__(self, a): # x - y
# print('{} - {}'.format(self, a))
nu = self.p * a.q - a.p * self.q
di = self.q * a.q
return Rational(nu, di)
def __mul__(self, a): # x * y
# print('{} * {}'.format(self, a))
nu = self.p * a.p
di = self.q * a.q
return Rational(nu, di)
def __truediv__(self, a): # x / y
# print('{} * {}'.format(self, a))
nu = self.p * a.q
di = self.q * a.p
return Rational(nu, di)
def __eq__(self, a): # x == y
# print('{} == {}'.format(self, a))
return self.p == a.p and self.q == a.q
if __name__ == '__main__':
r = Rational(1, 4)
s = Rational(3, 8)
t = Rational(2, 8)
print(r + s) # Ratinal.__add__(r, s)
print(r - s)
print(r * s)
print(r / s)
print(r == s)
print(r == t)
```
---
## 繼承(補充)

----
```python
class Dog:
def __init__(self, name, color):
self.name = name
self.color = color
def sound(self):
print("Woof")
class Cat:
def __init__(self, name, weight):
self.name = name
self.weight = weight
class Vampire:
def __init__(self, name, age):
self.name = name
self.age = age
def sound(self):
print("Wryyyyyyyy!!")
def time_stop(self):
print("Za warudo!")
```
----
Same!
```python
class Animal:
def __init__(self, name):
self.name = name
def hello(self):
print(self.name)
class Dog(Animal):
def __init__(self, name, color):
super().__init__(name)
self.color = color
def sound(self):
print("Woof")
class Cat(Animal):
def __init__(self, name, weight):
super().__init__(name)
self.weight = weight
class Vampire(Animal):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def sound(self):
print("Wryyyyyyyy!!")
def time_stop(self):
print("Za warudo!")
```