這一節心累,反覆看多遍才理清頭緒,想跟整理筆記花一天時間,老了就是要服氣!
面向對象技術簡介
類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。
類變量:類變量在整個實例化的對象中是公用的。類變量定義在類中且在函數體之外。類變量通常不作爲實例變量使用。
數據成員:類變量或者實例變量用於處理類及其實例對象的相關的數據。
方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱爲方法的重寫。
實例變量:定義在方法中的變量,只作用於當前實例的類。
繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個派生類的對象作爲一個基類對象對待。例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關係(例圖,Dog是一個Animal)。
實例化:創建一個類的實例,類的具體對象。
方法:類中定義的函數。
對象:通過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。
Example:
class Employee:
# empCount 變量是一個類變量,它的值將在這個類的所有實例之間共享。你可以在內部類或外部類使用 Employee.empCount 訪問
empCount = 0
# 第一種方法__init__()方法是一種特殊的方法,被稱爲類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法
# self 代表類的實例,self 在定義類的方法時是必須有的,雖然在調用時不必傳入相應的參數
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d" % Employee.empCount,self.name) # 未調用此方法 所以不輸出
def displayEmployee(self):
print("Name : ", self.name, ", Salary: ", self.salary)
# 內容被封裝到了對象 emp1 和 emp2 中,每個對象中都有 name 和 salary 屬性
"創建 Employee 類的第一個對象"
emp1 = Employee("Zara", 2000)
"創建 Employee 類的第二個對象"
emp2 = Employee("Manni", 5000)
# emp1.displayCount() #調用第displayCount()方法
emp1.displayEmployee() # 調用displayEmployee()方法
emp2.displayEmployee() # 調用displayEmployee()方法
print("Total Employee %d" % Employee.empCount)
輸出結果:
Name : Zara , Salary: 2000
Name : Manni , Salary: 5000
Total Employee 2
#####################################----分----割----線----############################################
類繼承:
# 1、Python的類可以繼承多個類,Java和C#中則只能繼承一個類
# 2、Python的類如果繼承了多個類,那麼其尋找方法的方式有兩種,分別是:深度優先和廣度優先
#3、 經典類和新式類,從字面上可以看出一個老一個新,新的必然包含了跟多的功能,也是之後推薦的寫法,從寫法上區分的話,如果 經 典 當前類或者父類繼承了object類,那麼該類便是新式類,否則便是經典類。
Example:
class D:
def bar(self):
print('D.bar')
class C(D):
def bar(self):
print('C.bar')
class B(D):
def bar(self):
print('B.bar')
class A(B, C):
def bar(self):
print('A.bar')
a = A()
# 執行bar方法時
# 首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麼有,則繼續去D類中找,如果D類中麼有,則繼續去C類中找,如果還是未找到,則報錯
# 所以,查找順序:A --> B --> D --> C
# 在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了
a.bar()
輸出結果:
A.bar
Example:
class D(object):
def bar(self):
print('D.bar')
class C(D):
def bar(self):
print('C.bar')
class B(D):
def bar(self):
print('B.bar')
class A(B, C):
def bar(self):
print('A.bar')
a = A()
# 執行bar方法時
# 首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麼有,則繼續去C類中找,如果C類中麼有,則繼續去D類中找,如果還是未找到,則報錯
# 所以,查找順序:A --> B --> C --> D
# 在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了
a.bar()
輸出結果:
A.bar
# 經典類:首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麼有,則繼續去D類中找,如果D類中麼有,則繼續去C類中找,如果還是未找到,則報錯
# 新式類:首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麼有,則繼續去C類中找,如果C類中麼有,則繼續去D類中找,如果還是未找到,則報錯
# 注意:在上述查找過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了
#####################################----分----割----線----############################################
多態:
# Pyhon不支持Java和C # 這一類強類型語言中多態的寫法,但是原生多態,其Python崇尚“鴨子類型”。
Example:
class F1:
pass
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
# 由於在Java或C#中定義函數參數時,必須指定參數的類型
# 爲了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類
# 而實際傳入的參數是:S1對象和S2對象
def Func(F1 obj):
"""Func函數需要接收一個F1類型或者F1子類的類型"""
print(obj.show())
s1_obj = S1()
Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.show
Example:
class F1:
pass
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
def Func(obj):
print(obj.show())
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
輸出結果:
S1.show
None
S2.show
None
#####################################----分----割----線----############################################
面向對象是一種編程方式,此編程方式的實現是基於對 類 和 對象 的使用
類 是一個模板,模板中包裝了多個“函數”供使用
對象,根據模板創建的實例(即:對象),實例用於調用被包裝在類中的函數
面向對象三大特性:封裝、繼承和多態
什麼樣的代碼纔是面向對象?
答:從簡單來說,如果程序中的所有功能都是用 類 和 對象 來實現,那麼就是面向對象編程了。
函數式編程 和 面向對象 如何選擇?分別在什麼情況下使用?
答:須知:對於 C# 和 Java 程序員來說不存在這個問題,因爲該兩門語言只支持面向對象編程(不支持函數式編程)。而對於 Python 和 PHP 等語言卻同時支持兩種編程方式,且函數式編程能完成的操作,面向對象都可以實現;而面向對象的能完成的操作,函數式編程不行(函數式編程無法實現面向對象的封裝功能)。
所以,一般在Python開發中,全部使用面向對象 或 面向對象和函數式混合使用
# 面向對象的應用場景:
# 1. 多函數需使用共同的值,如:數據庫的增、刪、改、查操作都需要連接數據庫字符串、主機名、用戶名和密碼
class SqlHelper:
def __init__(self, host, user, pwd):
self.host = host
self.user = user
self.pwd = pwd
def 增(self):
# 使用主機名、用戶名、密碼(self.host 、self.user 、self.pwd)打開數據庫連接
# do something
# 關閉數據庫連接
def 刪(self):
# 使用主機名、用戶名、密碼(self.host 、self.user 、self.pwd)打開數據庫連接
# do something
# 關閉數據庫連接
def 改(self):
# 使用主機名、用戶名、密碼(self.host 、self.user 、self.pwd)打開數據庫連接
# do something
# 關閉數據庫連接
def 查(self):
# 使用主機名、用戶名、密碼(self.host 、self.user 、self.pwd)打開數據庫連接
# do something
# 關閉數據庫連接# do something
# 2. 需要創建多個事物,每個事物屬性個數相同,但是值的需求
# 如:張三、李四、楊五,他們都有姓名、年齡、血型,但其都是不相同。即:屬性個數相同,但值不相同
class Person:
def __init__(self, name ,age ,blood_type):
self.name = name
self.age = age
self.blood_type = blood_type
def detail(self):
temp = "i am %s, age %s , blood type %s " % (self.name, self.age, self.blood_type)
print(temp)
zhangsan = Person('張三', 18, 'A')
lisi = Person('李四', 73, 'AB')
yangwu = Person('楊五', 84, 'A')
zhangsan.detail()
輸出結果:
i am 張三, age 18 , blood type A