目錄
一、面向對象的基本概念
二、類和對象
1.類
2.對象
三、屬性(數據)和方法
1.數據
1.1.實例數據
1.2.類數據
2.方法
2.1.實例方法
2.2.類方法
3.數據和方法的綜合使用
四、面向對象三大特性
1.封裝
2.繼承
2.1.單繼承
2.2.多繼承
2.3.混合類
2.4.方法解析順序(MRO)
3.多態
五、數據訪問級別
1.公有
2.私有
3.保護
六、類的成員
特點
七、魔法函數
1.__init__
2.__str__
3.數學比較
4.__len__
5.__new__(cls)、__del__
6.上下文管理器
總結
一、面向對象的基本概念
面向對象編程(Object-Oriented Programming,OOP)是一種編程范式,它以"對象"為核心組織代碼和數據,他更適合一些復雜項目的開發,通過封裝方法和屬性,讓代碼的復用性增強,提高了開發效率。
二、類和對象
類是抽象的,對象是具體的。
1.類
類是創建對象的藍圖或模板,它定義了對象的屬性和行為。下面是定義一個類:
class MyClass:"""一個簡單的類示例"""pass
2.對象
對象是類的實例,是根據類創建的具體實體。以下是對上述類的一個實例化對象:
obj = MyClass()
三、屬性(數據)和方法
1.數據
所謂數據,就是事物所具有的一定的特征。
1.1.實例數據
實例數據屬于特定實例的變量,通過self
在方法中定義和訪問。例如,下面定義了一個學生Student類,在類里面定義了兩個屬性,分別是self.name和self.age,這個就是實例數據。
class Student:def __init__(self, name, age):self.name = name # 實例屬性self.age = age # 實例屬性stu1 = Student("張三", 20)
stu2 = Student("李四", 22)
print(stu1.name) # 輸出: 張三
print(stu2.name) # 輸出: 李四
1.2.類數據
類數據屬于類本身的變量,所有實例共享同一個類屬性,定義在類內部但在方法外部。我們在學生類里面定義了類數據school,在類外部實例化兩個對象,運行結果是都能打印出這個屬性值。
class Student:school = "清華大學" # 類屬性def __init__(self, name):self.name = namestu1 = Student("王五")
stu2 = Student("趙六")
print(stu1.school) # 輸出: 清華大學
print(stu2.school) # 輸出: 清華大學
2.方法
所謂方法,就是事物所具有的一定的行為。
2.1.實例方法
實例方法的第一個參數必須是self
,表示當前實例,可以訪問和修改實例屬性。下面的bark就是我們的實例方法,self表示當前的實例。
class Dog:def __init__(self, name):self.name = namedef bark(self): # 實例方法print(f"{self.name}在汪汪叫!")dog = Dog("阿黃")
dog.bark() # 輸出: 阿黃在汪汪叫!
2.2.類方法
類方法使用@classmethod
裝飾器,第一個參數是cls
,表示當前類,可以訪問和修改類屬性。get_count(cls)這個方法第一個參數是cls,說明當前是類這個級別,在類外面以對象的形式調用。
class Student:count = 0 # 類屬性@classmethoddef get_count(cls):return cls.countdef __init__(self):Student.count += 1stu1 = Student()
stu2 = Student()
print(Student.get_count()) # 輸出: 2
3.數據和方法的綜合使用
問題:創建一個圓Circle類,為該類提供一個初始化方法,用于初始化半徑;為該類提供兩個方法,方法一用 于求圓的面積,方法二用于求圓的周長。
class Circle:PI = 3.14# 初始化方法def __init__(self, radius):self.radius = radiusdef get_area(self):return Circle.PI * self.radius ** 2def get_perimeter(self):return 2 * Circle.PI * self.radiusc = Circle(1)
print(c.get_area())
print(c.get_perimeter())
四、面向對象三大特性
1.封裝
將數據和操作數據的方法綁定在一起即為封裝。封裝在類中非常常見,封裝完成后,進行類的實例化即可。
class Product:def __init__(self, name, price):self.name = nameself.price = pricedef get_price(self):return self.priceclass Food:def __init__(self, weight):self.weight = weightdef get_qian(self):print(Product("食物", 49.9).price)
f = Food(20)
f.get_qian() # 輸出49.9
2.繼承
2.1.單繼承
一個子類只繼承一個父類,這樣的繼承叫做單繼承。
# 繼承
class Animal:def __init__(self, age):self.age = agedef __str__(self):return "hello"def shark(self):print("動物都會叫")a = Animal(5)
print(a, a.age)
a.shark()class Dog(Animal):def __init__(self, age, name):super().__init__(age)self.name = namedef __str__(self):return "這是一只狗狗"def shark(self):print("狗正在叫喊")d = Dog(7, "lida")
print(d, d.age, d.name)
d.shark()class AQ(Dog):def __init__(self, age, name, height):super().__init__(age, name)self.height = heightdef __str__(self):return "這是一只Dog隊"def shark(self):print("團隊活動正在精心準備進行")aq = AQ(9, "huange", 2.5)
print(aq, aq.age, aq.name, aq.height)
aq.shark()
2.2.多繼承
多繼承的一個子類可以繼承多個父類。
class Father:def __init__(self, money):self.money = moneydef get_money(self):print(self.money)class Mother:def __init__(self, beautiful):self.beautiful = beautifuldef get_beautiful(self):print(self.beautiful)class Son(Father, Mother):def __init__(self, money, beautiful):# # 多繼承中,子類只能繼承(識別)第一個父類# # super().__init__(money)# # super().__init__(beautiful)# # 多繼承使用類調用,要有selfFather.__init__(self, money)Mother.__init__(self, beautiful)def show(self):return f"共計{self.money}"s = Son("100", "漂亮")
s.get_money()
s.get_beautiful()
當處于多繼承時,子類使用超類調用,只能繼承(識別第一個父類),因此,我們一般會通過“父類對象.__init__()”類調用的方法進行完整的繼承。
2.3.混合類
一種特殊的多繼承用法,用于添加功能,通常是以Mixin結尾。
class Life:def __init__(self, hb):self.hb = hbdef __str__(self):return f"生命值{self.hb}"class Animal:passclass SwimmingAbleMixin:def swim(self):print(f"魚可以游泳")class Fish(Life, SwimmingAbleMixin):passf = Fish("100")
print(f) # 生命值100
f.swim() # 魚可以游泳
2.4.方法解析順序(MRO)
Python使用C3算法確定多繼承時的查找順序。
class A:passdef __str__(self):return "A"class B11:pass# def __str__(self):# return "B11"class B12:def __str__(self):return "B12"class B1(B11, B12):pass# def __str__(self):# return "B1"class B2:pass# def __str__(self):# return "B2"class B(B1, B2):pass# def __str__(self):# return "B"class C(B, A):pass# def __str__(self):# return "C"c = C()
print(c)
3.多態
多態就是不同類的對象對同一消息做出不同的響應。一般都是編譯型語言擁有的概念。
class Employee:def __init__(self, name, salary):self.name = nameself.salary = salarydef get_salary(self):raise NotImplemented("子類必須重寫父類")class Manage(Employee):def __init__(self, bonus, name, salary):super().__init__(name, salary)self.bonus = bonusdef get_salary(self):total = self.salary + self.bonusreturn f"{self.name}的總工資為{total}"m = Manage(500, "劉強", 8000)
print(m.get_salary()) # 輸出:劉強的總工資為8500
上述代碼創建另一個基類和一個子類,兩個類都有同一種方法get_salary(),但是需要通過子類重寫父類實現。
- 父類中的raise NotImplemented("子類必須重寫父類")表示子類中必須要實現此方法,否則程序會出錯。
- 子類中super().__init__(name, salary)表明繼承父類中的兩個屬性(數據)。
五、數據訪問級別
1.公有
默認格式,類內通過self訪問,類外通過對象訪問。
class MyClass:def __init__(self):self.public_var = "I'm public"def public_method(self):return "Public method"obj = MyClass()
print(obj.public_var) # 可以直接訪問
print(obj.public_method()) # 可以直接調用
2.私有
__開頭,類內以self訪問,類外不可訪問。
class MyClass:def __init__(self):self.__private_var = "I'm private"def __private_method(self):return "Private method"obj = MyClass()
# print(obj.__private_var) # 直接訪問會報錯
# print(obj.__private_method()) # 直接調用會報錯# 通過名稱修飾后的名稱仍可訪問(但不應該這樣做)
print(obj._MyClass__private_var) # 可以訪問
print(obj._MyClass__private_method()) # 可以調用
3.保護
_開頭,本類內可以訪問,本類外也可以訪問,但不推薦;通常是在子類中使用。
class MyClass:def __init__(self):self._protected_var = "I'm protected"def _protected_method(self):return "Protected method"obj = MyClass()
print(obj._protected_var) # 仍然可以訪問,但不建議
print(obj._protected_method()) # 仍然可以調用,但不建議
六、類的成員
除了上述介紹的類的成員,下面還有一種類成員,就是靜態方法。靜態方法(Static Method)是一種屬于類但不屬于類的任何特定實例的方法。這意味著你可以調用靜態方法而不創建類的實例。靜態方法通常用于實現那些不依賴于類實例狀態的工具方法或輔助方法。
class MyClass:@staticmethoddef static_method():print("Called static_method")@staticmethoddef sum(a, b):print(a + b)@staticmethoddef max(a, b):return a if a > b else bMyClass.static_method()
MyClass.sum(3, 5)
print(MyClass.max(12, 5))
上述代碼中,我們在調用靜態方法時,并沒有進行實例化,而是通過函數名直接調用。
特點
-
無需實例:你可以直接通過類名調用靜態方法,無需創建類的實例。
-
不接受?
self
?或?cls
:靜態方法不會自動接收任何類或實例作為第一個參數。 -
用途:靜態方法通常用于實現那些不需要訪問類實例狀態的函數,例如工廠方法、工具函數等。
七、魔法函數
1.__init__
__init__函數用于初始化self。
class Light:def __init__(self):"""初始化函數:用于初始化selfself就是類執行產生的對象"""self.color = "紅色"print(id(self))def set_light(self, color):self.color = colorprint(self.color)def get_light(self):print(self.color)創建對象l1
l1 = Light()
l1.set_light("綠色")
print(id(l1), l1.color)print("++++++++++++++")創建對象l2
l2 = Light()
l2.get_light()
2.__str__
__str__函數返回的結果必須是字符串,也是自動調用。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"Person(name='{self.name}', age={self.age})"p = Person("Alice", 30)
print(p) # 輸出: Person(name='Alice', age=30)
3.數學比較
數學比較的魔法函數有__gt__、__ge__、__lt__、__le__、__eq__和__ne__。所有的魔法函數不需要主動調用,以__**__為格式。
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):"""對象的字符串表示:return: 字符格式"""return f"{self.name}:{self.age}"def __gt__(self, other):"""重寫,實例比較的>:param other::return:"""return self.age > other.agedef __ge__(self, other):return self.age >= otherdef __lt__(self, other):"""小于:param other::return:"""return self.age < other.agedef __le__(self, other):return self.age <= other.agedef __ne__(self, other):return self.age != other.agedef __eq__(self, other):return self.age == other.agep1 = Person("abc", 20)
print(p1)
p2 = Person("jsp", 26)
print(p1 <= p2)
4.__len__
__len__用于定義對象的長度。當對對象調用內置的?len()
?函數時,Python 會自動調用該對象的?__len__
?方法。
class MyCollection:def __init__(self, items):self.items = itemsdef __len__(self):return len(self.items)collection = MyCollection([1, 2, 3, 4, 5])
print(len(collection)) # 輸出: 5
5.__new__(cls)、__del__
構造函數:創建類的新實例對象;析構函數:用于對象銷毀的特殊方法
class Animal:# 必須返回一個類的實例,否則init__,方法不會被調用。def __new__(cls, *args, **kwargs):# cls 是當前類對象,必須作為參數傳入instance = super().__new__(cls)return instancedef __init__(self):print("初始化函數執行了", id(self))def __del__(self):print("正在銷毀...")
# 先調用 __new__ 創建對象,再調用 __init__ 初始化對象
a = Animal()
print(a, id(a))
6.上下文管理器
__enter__:實現資源的獲取;
__exit__:實現資源的釋放。
class Myopen:def __init__(self, filename, mode):self.filename = filenameself.mode = modeself.file = Nonedef __enter__(self):self.file = open(self.filename, self.mode)return self.filedef write(self, msg):self.file.write(msg)def __exit__(self, exc_type, exc_val, exc_tb):# exc_type:異常類型# exc_val:異常值# exc_tb:追蹤信息if self.file:self.file.close()with Myopen("myfile.txt", "w") as f:f.write("Hello world!")
總結
面向對象編程(OOP)是一種以對象為核心的編程范式,其核心概念包括類與對象、屬性與方法、三大特性(封裝、繼承、多態)以及數據訪問控制等。類作為對象的抽象模板,通過定義屬性和方法來描述實體的特征和行為,其中屬性分為實例數據(對象獨有)和類數據(類共享),方法則包括實例方法(操作實例數據)、類方法(操作類數據)等。面向對象三大特性中,封裝通過訪問控制(公有、私有、保護)隱藏實現細節;繼承支持單繼承和多繼承,通過方法解析順序(MRO)解決多繼承沖突;多態則允許不同類對象對同一方法產生不同行為。類的特殊成員如魔法函數(如__init__構造對象、__str__定義字符串表示、__len__支持長度計算等)賦予類更靈活的行為能力。上下文管理器(__enter__/__exit__)等高級特性進一步擴展了對象的功能邊界。這些概念共同構成了面向對象編程的完整體系,通過抽象、模塊化和代碼復用提升軟件的可維護性和擴展性。