文章目錄
- 一、類與實例:從抽象到具體
- 1?? 類(Class):抽象的模板
- 2?? 實例(Instance):具體的對象
- 3?? `__init__` 方法:初始化實例屬性
- 二、封裝:數據與邏輯的“打包”
- 1?? 方法的定義與調用
- 2?? 私有屬性:限制外部直接訪問
- 三、繼承:代碼復用的利器
- 1?? 基本用法
- 2?? 繼承的優勢
- 四、多態:靈活的接口適配
- 1?? 多態體現:
- 2?? 優勢
- 五、類屬性與實例屬性
- 1?? 實例屬性:每個實例獨有
- 2?? 類屬性:類本身擁有,所有實例共享
- 六、對象信息的獲取
- 七、鴨子類型 🦆
- ? 總結歸納
面向對象編程(OOP)是 Python 編程的核心思想之一,它通過封裝、繼承、多態等特性實現代碼的復用與擴展。本文將系統梳理 Python 中 OOP 的核心概念,幫助你快速掌握面向對象編程的精髓。
一、類與實例:從抽象到具體
1?? 類(Class):抽象的模板
類是對現實事物的抽象描述,定義了對象的屬性(數據)和方法(行為)。使用 class
關鍵字定義,類名通常以大寫字母開頭,默認繼承自 object
類(所有類的根類)。
class Student(object):# 類的屬性和方法將在這里定義pass
2?? 實例(Instance):具體的對象
實例是根據類創建的具體個體,每個實例擁有獨立的數據。通過「類名 + ()」創建實例:
bart = Student()
lisa = Student()print(bart) # <__main__.Student object at 0x000001>
print(lisa) # <__main__.Student object at 0x000002>
3?? __init__
方法:初始化實例屬性
__init__
方法在創建實例時自動調用,用于初始化屬性:
class Student(object):def __init__(self, name, score):self.name = nameself.score = scorebart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)print(bart.name) # Bart Simpson
print(lisa.score) # 87
二、封裝:數據與邏輯的“打包”
封裝是將數據(屬性)和操作數據的方法(函數)打包在一起,隱藏實現細節,僅通過公開方法訪問。
1?? 方法的定義與調用
class Student(object):def __init__(self, name, score):self.name = nameself.score = scoredef print_score(self):print(f"{self.name}: {self.score}")bart.print_score() # Bart Simpson: 59
2?? 私有屬性:限制外部直接訪問
class Student(object):def __init__(self, name, score):self.__name = nameself.__score = scoredef get_name(self):return self.__namedef set_score(self, score):if 0 <= score <= 100:self.__score = scoreelse:raise ValueError("分數必須在 0-100 之間")
🔎 為什么使用私有屬性?
- 避免外部修改敏感數據
- 封裝實現細節,提高安全性和可靠性
三、繼承:代碼復用的利器
繼承允許子類復用父類的屬性和方法,并可擴展新功能或重寫已有方法。
1?? 基本用法
class Animal(object):def run(self):print("動物在奔跑...")class Dog(Animal):passclass Cat(Animal):def run(self):print("貓在奔跑...")
2?? 繼承的優勢
dog = Dog()
dog.run() # 動物在奔跑...cat = Cat()
cat.run() # 貓在奔跑...
? 避免重復代碼
? 子類可自定義行為
四、多態:靈活的接口適配
多態允許不同子類以統一接口調用,實現不同表現。
1?? 多態體現:
def run_twice(animal):animal.run()animal.run()run_twice(Dog()) # 動物在奔跑...
run_twice(Cat()) # 貓在奔跑...class Tortoise(Animal):def run(self):print("烏龜在緩慢爬行...")run_twice(Tortoise()) # 烏龜在緩慢爬行...
2?? 優勢
- ? 調用方無需關心具體類型
- ? 遵循開閉原則:開放擴展,封閉修改
五、類屬性與實例屬性
1?? 實例屬性:每個實例獨有
bart.age = 8
lisa.age = 9
2?? 類屬性:類本身擁有,所有實例共享
class Student(object):count = 0def __init__(self, name):self.name = nameStudent.count += 1bart = Student('Bart')
print(Student.count) # 1lisa = Student('Lisa')
print(Student.count) # 2
?? 注意:實例屬性會遮蔽同名類屬性!
六、對象信息的獲取
Python 提供豐富的內置函數動態獲取對象信息:
函數 | 作用 |
---|---|
type(obj) | 獲取類型 |
isinstance(obj, 類型) | 判斷是否為某類或其子類實例 ? |
dir(obj) | 列出所有屬性和方法 |
hasattr(obj, 'attr') | 判斷是否有某屬性 |
getattr(obj, 'attr') | 獲取屬性值,支持默認值 |
setattr(obj, 'attr', val) | 設置屬性 |
?示例:
class MyObject(object):def __init__(self):self.x = 9def power(self):return self.x * self.xobj = MyObject()print(hasattr(obj, 'x')) # True
print(getattr(obj, 'x')) # 9
print(getattr(obj, 'y', 404)) # 404
fn = getattr(obj, 'power')
print(fn()) # 81
七、鴨子類型 🦆
Python 作為動態語言,不依賴嚴格的繼承關系,而是通過 “鴨子類型” 判斷對象是否符合要求:“如果一個對象看起來像鴨子,叫起來像鴨子,那它就是鴨子”。
- 例如,只要一個對象有 read() 方法,就可以被視為 “類文件對象”,無需繼承自某個特定的類:
def read(self):return "模擬文件內容"# 接收類文件對象的函數
def read_data(fp):print(fp.read())# 傳入自定義的 FileLike 實例(無需繼承)
read_data(FileLike()) # 模擬文件內容
💡 鴨子類型原則:只要有 .read()
方法,就可當作“類文件對象”使用!
? 總結歸納
OOP 概念 | 關鍵點說明 |
---|---|
類與實例 | 類是模板,實例是具體對象 |
__init__ | 初始化實例屬性 |
封裝 | 使用 __ 隱藏私有屬性,避免濫用 |
方法調用 | 第一個參數為 self ,由實例自動傳遞 |
繼承 | 子類繼承父類,減少重復代碼 |
多態 | 子類重寫方法,接口統一,行為多樣 |
類屬性 | 所有實例共享 |
實例屬性 | 各自獨立 |
類型判斷 | 推薦使用 isinstance() 判斷 |
鴨子類型 | 行為決定角色,而非繼承結構 |