---
###### tags: `資訊之芽`
---
# Class
講師:洪郁凱
---
Class類別 大綱
- 基本概念
- 屬性/隱藏
- 方法
- 繼承/聚合
----
大家好,我不是老糕
今天 我們來講
----
*Class*
----
有一派人說
Python世界裡的東西 都是由物件組成
----
所以只要精通物件,那麼你就在Python中無敵了
----
好啦可能不會(X)
----
## 基本概念
- python裡面的資料都是物件
- class像是物件的規格書
- 自訂的一種資料結構 (Optional)
- 利用類別 可以做出很多類似的物件(instance)
----
## 基本概念
一個class可以生很多物件!
----
## 基本概念
神奇的指令
檢查obj是不是用class做出來的
```python=
isinstance(obj,class) #回傳obj物件是否由class所縣立的
```
----
## 基本概念
```python=
isinstance([1,2,3],list)
```
list是一個class!?
----
## 基本概念
```python=
isinstance(5,int)
```
int也是一個class!!??
----
## 基本概念
那能不能直接查某物件是屬於哪個class的?
----
## 基本概念
想知道他是什麼class來的
可以用type()
```python=
type(3) # <class 'int'>
```
出現"class" 也有了解釋
----
### 不太基本但沒關係
```python=
class Itaewon():
pass
kim = Itaewon()
print(type(kim)) # <class '__main__.Itaewon'>
```
kim屬於Itaewon(梨泰院) Class
![](https://i.imgur.com/jVVXeJx.png =300x)
----
## 基本概念
基本語法
注意class的命名!
```python=
class Name(): #宣告 神秘括號
pass
object = Name() #建立物件
```
Reminder: Class的名字首字通常為大寫
----
## 小節整理
- class vs 物件
- 查找物件所屬class
- 宣告class
![](https://i.imgur.com/kViGy5F.png)
[ref](https://zh.wikipedia.org/wiki/小傑·富力士)
---
## 屬性
物件裡面可以裝載的資料的地方
----
## 屬性
```python=
class Food():
pass
bread = Food()
bread.price = 50 #從外面加入屬性
```
----
## 屬性
```python=
class Food():
def __init__(self): # 要加一個位置參數,代表新建立的物件
self.price = 50 # 透過初始化函式設定屬性
bread = Food()
print(bread.price) #取值方法
```
----
## 屬性
可能會讓你聯想到Dict?
```python=
bread = dict()
bread["price"] = 50
print(bread["price"]) #給Key 回傳Value
```
----
## self???
第一個self是何方神聖?
```python
class Food():
def __init__(): #故意不加self
# self.price = 50
pass
# __init__() takes 0 positional arguments but 1 was given
```
----
## self???
第一個self是何方神聖?
```python
class Food():
def __init__(): #故意不加self
# self.price = 50
pass
# __init__() takes 0 positional arguments but 1 was given
```
- _\_init__是製作物件時會被呼叫的函式,不必回傳東西
- 會給你即將出爐的物件 當作函式的第一個參數
----
## self???
第一個self是何方神聖?
```python
class Food():
def __init__(s): # 來看看第一個傳入的東西到底是啥
print(s)
print(type(s))
print(id(s))
bread = Food()
print(id(bread))
```
----
## self???
第一個self是何方神聖?
```python
class Food():
def __init__(s): # 來看看第一個傳入的東西到底是啥
print(s)
print(type(s))
print(id(s))
bread = Food()
print(id(bread))
```
- 透過查看id,可以知道__init__吃的第一個參數就是物件自己
- 請注意class Food()/bread = Food(),兩者括號裡面放的東西天差地遠
----
## 屬性
```python=
class Food():
def __init__(self,p): # 第二個位置參數才會是food括號中的第一個參數
self.price = p # 透過初始化函式設定屬性
bread = Food(39)
print(bread.price) #取值方法
```
----
## 屬性
如何刪除呢
```python=
class Food():
def __init__(self,p): #加入屬性的方法
self.price = p
bread = Food(39)
del bread.price
print(bread.price) # 會壞掉
```
----
## 屬性
一個簡單的範例
```python=
class Food():
def __init__(self,pri,siz,pop):
self.price = pri
self.size = siz
self.popularity = pop
cupcake = Food(39,"M",100)
```
----
## 整理
- __init\_\_ 函式參數 呼叫時機
- 物件的屬性加入/刪除
----
## QA Time
其他延伸:
- getter/setter
- private attribute
- syntatic sugar
----
## 小練習
```
寫一個class名為Drink
並生成兩個物件
有store price size flavor屬性
分別為"Starbucks" 180 "L" "抹茶奶霜星冰樂"
及 "麻古茶坊" 50 "M" "椰果奶茶"
之後練習一下把price刪除 改用point(分別為400,100)
```
----
## 好康大放送
```python=
class Car():
def __init__(self,price):
self.price = price
def drive(self):
print("AMG開大的")
bmw = Car(100)
class Mini_Car(Car):
def drive(self):
print("開小車")
mini_benz = Mini_Car(130)
bmw.price # 100
mini_benz.price # 130
```
---
## 方法
物件裡面能放資料
那能不能放函式?
----
## 方法
recall
```python=
str1 = "This is an example"
str1.count(" ") # 3
str2 = "A"
str2.isalpha() # True
[177,63,20,9,28].sort()
```
----
## 方法
規定怎麼去取用不同物件裡的內容
- 實例方法 Instance Method 針對物件
- 類別方法 Class Method 針對整個類別
- 靜態方法 Static Method
----
## 宣告方法
```python=
class Food():
def eat(): #在裡面宣告
print('yummy')
```
----
## 宣告方法
```python=
def eat(): #在裡面宣告
print('yummy')
class Food():
pass
Food.eat = eat
```
----
## 宣告方法
```python=
class Food():
pass
Food.eat = lambda : print('yummy') #從外部加入
# 宣告方法的方法(X)
```
optional:lambda 函式
----
## 宣告方法
方法內跟主程式內取值的作法一樣
```python=
class Food():
sold = 23
def count():
print(Food.sold,'packs of food has been sold')
```
----
## 實例方法
因為是針對各個物件的
實例方法需要傳入物件
```python=
def __init__(self):
```
----
## 實例方法
例如剛剛的初始化函式
```python=
class Food():
def __init__(self):
self.price = 50
```
----
## 實例方法
傳遞參數
```python=
class Food():
def set_price(self,in_price): #還記得self嗎
self.price = in_price
a = Food()
a.set_price(20)
```
----
## 實例方法
初始化函數傳遞參數的範例
```python=
class Food():
def __init__(self,pri,siz,pop):
self.price = pri
self.size = siz
self.popularity = pop
cupcake = Food(39,"M",100)
```
---
## 類別方法
class method
只影響這個類別 以及這個類別之後建立的物件
```python=
class Pinky():
flavor = 3 # 類別屬性
@classmethod
def cm(cls):
print(f"{cls} has {cls.flavor} flavors.")
strawberry = Pinky()
strawberry.cm()
Pinky.cm()
```
----
## 類別方法
可以用這個方式計算生出物件數量
```python=
class Food():
ind = 0
def __init__(self):
self.ind = Food.ind
Food.ind += 1
@classmethod
def num_of_food(cls):
print(f'有{cls.ind}個食物物件')
Food.num_of_food()
```
----
## 類別方法
可以用這個方式計算生出物件數量
```python=
class Food():
ind = 0
def __init__(self):
self.ind = Food.ind
Food.ind += 1
@classmethod
def num_of_food(cls):
print(f'有{cls.ind}個食物物件')
Food.num_of_food()
```
\@classmethod 是一種語法糖
---
## 靜態方法
static method
不傳入實例 也不傳入類別
```python=
class Food():
@staticmethod
def promote():
print('全面特價!')
Food.promote()
```
----
## 方法整理
| X | 實例方法 | 類別方法 | 靜態方法 |
| -------- | ---------- | ------------ | ------------- |
| 對象 | 物件 | 類別 | None |
| 參數 | func(self) | func(cls) | func() |
| 呼叫 | obj.func() | cls.func() | cls.func() |
----
## QA Time
在class/物件之中放函式的過程還順利嗎?
----
## 練習時間!
```
寫一個class 名叫 Motor
Motor有一個屬性叫GonDaoPrice(公道價) 81000
生出兩個物件
有屬性 brand, name, discount, cc_motor
分別為 "Honda", "CB150r", 5000, 150
及 "YAMAHA", "勁戰六", 12000, 150
其中有一個實例方法getPrice 輸出GonDaoPrice - discount
```
----
## 好康大放送
```python=
class NewPinky():
def __init__(self,f):
self.flavor = f
def __str__(self):
return f'My flavor is {self.flavor}'
p = NewPinky("Grape")
print(p) # My flavor is Grape
```
----
## 好康大放送
```python=
a = str(1234)
print(a) # "1234"
```
---
## 魔術方法
長相,呼叫方式不一樣的函式
```python=
print(1+2)
print('1'+'2')
print([1,]+[2,])
```
----
## 魔術方法
來試圖寫一個自己的數字class
```python=
class num():
def __init__(self,inp):
self.value = inp
```
----
## 魔術方法
呼叫方式不一樣
```python=
class num():
def __init__(self,inp):
self.value = inp
def __add__(self,other):
print('歡迎來到魔術方法')
return self.value + other.value
a = num(2)
b = num(3)
print(a+b)
```
----
## 魔術方法
不同型別也能用!
```python=
class num():
def __init__(self,inp):
self.value = inp
def __add__(self,other):
print('歡迎來到魔術方法')
return self.value + other.value
class food():
def __init__(self,inp):
self.value = inp
a = num(2)
b = food(3)
print(a+b)
```
----
## 魔術方法
運算類
| 魔術方法 | 對應符號 |
| ----------------- | -------- |
| \_\_add__(a,b) | a+b |
| \_\_sub__(a,b) | a-b |
| \_\_mul__(a,b) | a\*b |
| \_\_truediv__(a,b) | a/b |
| \_\_floordiv__(a,b) | a//b |
| \_\_pow__(a,b) | a\*\*b |
| \_\_mod__(a,b) | a%b |
----
## 魔術方法
比較類
| 魔術方法 | 對應符號 |
| ----------- | -------- |
| \_\_eq__(a,b) | a==b |
| \_\_ne__(a,b) | a!=b |
| \_\_lt__(a,b) | a<b |
| \_\_gt__(a,b) | a>b |
| \_\_le__(a,b) | a<=b |
| \_\_ge__(a,b) | a>=b |
----
## 魔術方法
其他
| 魔術方法 | 對應 |
| -------- | -------- |
| \_\_new__(cls,) | 新增物件用的 |
| \_\_init__(self,) | 初始化物件用的 |
| \_\_str__(self) | 被當成字串的時候用的 |
| \_\_repr__(self) | 在互動模式下被呼叫的 |
| \_\_del__(self) | 在解構物件用的 |
| \_\_int__(self) | 被int()呼叫用的 |
[其他魔術](https://www.tutorialsteacher.com/python/magic-methods-in-python)
---
## 多型 Duck Type
概念:寫不同類別方法時
讓不同類別的物件一起運算
----
## 多型 Duck Type
> if it looks like a duck swims like a duck and quacks like a duck then it probably is a duck
----
## 多型 Duck Type 範例
```python=
a = [1,2,3]
b = '123'
print(len(a),len(b))
print(a.count(1),b.count(1)) #型別不同 行為相同
```
---
## 還有好多沒講的
時間不夠 自己研究
- 繼承
- 裝飾器
- 線性加速器
- 本質主義的窠臼
- 克服外觀焦慮
- 金賽性傾向連續性理論
- 征服銀河系
----
## 作業
還沒選
{"metaMigratedAt":"2023-06-16T20:59:38.445Z","metaMigratedFrom":"Content","title":"Class","breaks":true,"contributors":"[{\"id\":\"9a14c697-53b2-4214-a12a-512e946e0176\",\"add\":14734,\"del\":5985}]"}