# Python Instance method, Class method and Static method
> [name=Tao]
> [TOC]
###### tags: `Python` `OOP`
## 說明
### Instance Method
最基本的方法,第一個參數要是 self ,指向這個物件本身
可以透過 self 來存取物件裡的其他 instance method 或是參數,來改變物件的狀態
### Class Method
:bulb: 宣告的時候要加上 `@classmethod` 這個 decorator 在 method 上方
class method 跟 instance 方法不同的點在於,他第一個參數是 cls 指向 class 本身,而非物件的本體,因此 class method 不能改變物件的狀態,但可以透過 cls 來變類別的狀態
### Static Method
:bulb: 宣告的時候要加上 `@staticmethod` 這個 decorator 在 method 上方
這個方法沒有 self 與 cls 這兩個參數,因此無法改變物件狀態,也無法改變類別的狀態
可以當成一般的 function 來使用
:::info
Static Method 不論透過類別(Class)或物件(Object)皆可呼叫,Python編譯器於執行期間(Runtime)不會傳入self及cls參數至靜態方法(Static Method)。
使用靜態方法(Static Method)有幾個優點是,在開發過程中可以避免新加入的開發人員意外改變類別(Class)或物件(Object)的狀態(因為方法中無self及cls參數),而影響到類別(Class)原始的設計。其二則是靜態方法(Static Method)在類別中是獨立的,所以有助於單元的測試。
:::
## 範例
```python
class MyClass:
def method(self):
return 'instance method called', self
@classmethod
def classmethod(cls):
return 'class method called', cls
@staticmethod
def staticmethod():
return 'static method called'
```
class method 跟 static method 可以直接呼叫
```python
MyClass.classmethod() # 可以執行!
MyClass.staticmethod() # 可以執行!
MyClass.method() # 會 TypeError: method() missing 1 required positional argument: 'self'
```
instance method 必須要有物件實體才可以呼叫
```python
mcls = MyClass() # 產生一個物件實體 (instance)
mcls.method() # 這樣才可以執行
# 或是直接這樣呼叫也行
MyClass().method()
```
### Class methods 與 Static methods 的比較
|比較項目 | Class Methods | Static Methods |
|-|-|-|
| 是否需要 cls 參數 | Yes | No |
|是否有能力存取類別的狀態或是方法 | Yes | No |
| 標記方式 | @classmethod | @staticmethod |
|用途 | 可做為建構子的替代與補充 | 僅做為使用的方法 |
### 使用情境範例: classmethod 做為建構子的替代與補充
例如宣告一個 Car 類別,Pizza 有很多種不同口味


## Reference
1. [Python's Instance, Class, and Static Methods Demystified](https://realpython.com/instance-class-and-static-methods-demystified/)
2. [ [Python物件導向]解析Python物件導向設計的3種類型方法(Instance,Class,Static Method)](https://www.learncodewithmike.com/2020/01/python-method.html)
3. [Python 的 Class methods 與 Static methods](https://itcosmos.co/python-class-methods-and-static-methods/)