深入理解 Python 中的 self 與物件導向原理
更新日期: 2024 年 11 月 18 日
本文為 python 物件導向系列文:第一篇
- 深入理解 Python 中的 self 與物件導向原理 👈所在位置
- 初學者指南:深入了解 Python 的 init 方法
- 理解 Python 中的 str 與 repr 方法
- 初學者指南:深入了解 Python 繼承
- 初學者指南:深入了解 Python 方法覆寫與 super()
- 初學者指南:深入了解 Python 中的多重繼承與鑽石問題
在 Python 的物件導向編程 (OOP) 中,self
是一個關鍵概念,負責將類別的實例與方法綁定在一起。
初學者經常會對 self
的用途感到疑惑,尤其是為什麼在定義類別方法時,需要將 self
作為第一個參數。
本文將透過範例逐步解析 self
的作用與原理,幫助你掌握 Python 的物件導向設計。
前言
當我們定義一個類別並試圖調用其方法時,可能會遇到一個令人困惑的錯誤提示:
class Cat:
def hi():
print('hi')
kitty = Cat()
kitty.hi()
執行上述程式時,會出現以下錯誤:
TypeError: Cat.hi() takes 0 positional arguments but 1 was given
為什麼會有多出來的參數?為什麼需要在方法中加入 self
?
接下來,我們將深入探討這些問題。
錯誤的原因:Python 的方法調用原理
在 Python 中,當你透過實例調用類別的方法時,例如 kitty.hi()
,Python 會自動將實例 kitty
傳遞給方法作為第一個參數。
上述程式的問題在於,方法 hi()
並沒有為這個自動傳入的參數保留位置。
因此,修正後的程式應該定義一個參數來接收這個實例,並依照慣例命名為 self
:
class Cat:
def hi(self): # 第一個參數用於接收實例
print('hi')
kitty = Cat()
kitty.hi()
執行結果:
hi
self
的作用與必要性
self
是指向實例本身的參數,它讓方法能夠訪問和操作該實例的屬性與行為。
連結實例與方法
透過 self
,Python 可以將方法綁定到具體的實例上。
當你調用 kitty.hi()
時:
- Python 自動將
kitty
傳遞給方法hi
作為第一個參數self
。
訪問實例屬性
self
允許我們在方法內訪問和修改實例屬性。
例如:
class Cat:
def __init__(self, name):
self.name = name # 定義實例屬性
def greet(self):
print(f"Meow! 我是 {self.name}")
kitty = Cat(name="Kitty")
kitty.greet()
執行結果:
Meow! 我是 Kitty
self.name
使用self
訪問屬性,確保每個實例都有自己的name
,而不會與其他實例混淆。
為什麼 self
必須顯式定義?
與其他語言(例如 JavaScript)的隱式關鍵字 this
不同,Python 採用了顯式的方式來處理實例參考。
這樣的設計有幾個好處:
- 清晰性
定義方法時,第一個參數self
明確表達了這是實例方法,對開發者更直觀。 - 一致性
Python 的一切皆為對象,包括方法。因此,所有方法(無論是否是類別方法)都以顯式的參數列表來表達。
與其他語言的比較
1. JavaScript 的 this
在 JavaScript 中,this
的值根據調用方式而變化,可能指向不同的物件。
例如:
class Cat {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Meow! 我是 ${this.name}`);
}
}
const kitty = new Cat("Kitty");
kitty.greet(); // 正常執行
const greetFn = kitty.greet;
greetFn(); // 出錯,this 指向全域物件
- JavaScript 的
this
依賴執行環境,容易出現指向錯誤的問題。
Python 的 self
Python 的 self
必須顯式傳遞,因此不會出現類似於 JavaScript 的 this
指向問題。
例如:
class Cat:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Meow! 我是 {self.name}")
kitty = Cat(name="Kitty")
kitty.greet() # 永遠正確地使用 self
self
明確綁定到實例,消除了模糊性。
總結
在 Python 中,self
是物件導向編程中不可或缺的部分:
- 它負責將方法與實例綁定,確保每個實例有自己的屬性與行為。
- 它提供了一種清晰且一致的方式來訪問實例數據,避免了像 JavaScript 那樣的指向問題。
雖然顯式傳遞 self
可能看起來麻煩,但它是 Python 設計中對清晰性和一致性的一種追求。
理解並掌握 self
的使用,將使你在物件導向設計中如魚得水。