面對對象基礎
1.面對對象不是所有情形都適用
1.1函數式編程
def fun1(arg1): pass def fun2(arg1,arg2): pass fun1("acker") fun2("...")
2.1面對對象編程
class humanBeing: def fun1(self, arg1): pass def fun2(self,arg1, arg2): pass obj1 = humanBeing() obj1.fun1(‘wuwen‘) obj2.fun2(‘henshuai‘)
結論:單從代碼的復雜程度來看,面對對象編程並不是適合所有情況
2.面對對象編程的格式規範:
a.定義類
class 類名: def 方法1(self,arg) pass
b.根據類創建對象(創建一個**類的實例)
使用對象去執行類中的方法(函數編程中,我們稱之為函數),如下圖為類與對象的關系
3.類的方法的默認參數self
self,形式參數,代指執行方法的對象,在python內部傳遞,為封裝而生
class humanBeing: def fun1(self, name): print(self, name)def fun2(self, name, gender): print(self, name, gender) obj1 = humanBeing() print(obj1) obj1.fun1(‘acker‘) obj1.fun2(‘acker‘, ‘female‘) #<__main__.humanBeing object at 0x02171210> #<__main__.humanBeing object at 0x02171210> wuwen #<__main__.humanBeing object at 0x02131490> wuwen female#總結:self為實例本身的內存地址
4.封裝:
當每個函數裏面都需要用到相同的參數(如上類方法中的name參數),我們可以提前把參數封裝到對象(實例)中去
class humanBeing: def fun1(self): print(self.name) def fun2(self, gender): print(self.name, gender) obj1 = humanBeing() obj1.name = ‘acker‘ obj1.fun1() #acker
5.用初始化封裝
類名+() ---->>> 自動執行類中的__init__方法;創建一個對象
在__init__方法中執行具體封裝的操作
__init__有一個特殊名字:構造方法
__del__有一個特殊的名字:析構器
class Oldboy: def __init__(self, backend, record): ‘‘‘ 構造方法 :param backend: :param record: ‘‘‘ # 普通字段 self.backend = backend self.record = record def fetch(self): print(self.backend) def add_record(self): print(self.record) def del_record(self): print(self.record) # 創建對象,並且封裝 obj1 = Oldboy(‘www.oldboy.org‘, ‘wohenshuai‘) # 執行方法,執行過程中可以根據self去obj1中去取已經封裝在裏面的數據 obj1.fetch() obj1.add_record() obj1.del_record()
5.1 小遊戲(可以用pickle存檔)
pickle可以將一個類的對象序列化
class person: def __init__(self, name, age, weight): self.Name = name self.Age = age self.Weight = weight def chi(self): self.Weight = self.Weight + 2 print("%s 吃" % self.Name) def bodybuilding(self): self.Weight = self.Weight - 1 import pickle # pickle 可以序列化對象,json只能處理字符串,數字,字典,列表與元組 # 遊戲存檔 ret = pickle.load(open(‘cundang.log‘, ‘rb‘)) print(ret) if ret: print(ret.Weight) else: o1 = person(‘小明‘, 5, 200) o1.bodybuilding() o1.chi() o1.chi() o1.chi() o1.chi() o1.chi() o1.chi() pickle.dump(o1, open(‘cundang.log‘, ‘wb‘)) # 將對象存檔
6.繼承
6.1 單繼承
‘‘‘ 子類繼承父類所有的功能 父類不能使用子類的功能 當父類和子類同時具有某種功能時: 對於由父類創建的對象,則使用自己的功能,因為它無法繼承自己的子類。 對於子類創建的的對象,我們也使用自己的功能,因為,優先級的先後。 ‘‘‘ class Animals: def chi(self): print(self.name + ‘吃‘) def he(self): print(self.name + ‘喝‘) def piao(self): print(‘愛piao‘) class Dog(Animals): def __init__(self, name): self.name = name def wang(self): print(self.name + ‘汪汪汪~‘) def piao(self): print(‘不愛piao‘) obj1 = Dog(‘桃桃‘) obj1.piao() ‘‘‘ 不愛piao ‘‘‘
6.2 多繼承(筆試易考)
#!/usr/bin env python # -*- coding:utf-8 -*- ‘‘‘ 在c++和java中,一個子類只能繼承一個父類 但是在python中,一個子類可以繼承多個父類 ‘‘‘ class Animals: def chi(self): print(self.name + ‘吃‘) def he(self): print(self.name + ‘喝‘) def piao(self): print(‘愛piao‘) class Uncle: def du(self): print(‘賭‘) def piao(self): print(‘很愛piao‘) class Dog(Animals, Uncle): ‘‘‘ 先繼承Animals和Uncle父類中不重復的方法 對不重復的方法:優先找自己,其次第一個父類Animals,最後第二個父類Uncle ‘‘‘ def __init__(self, name): self.name = name def wang(self): print(self.name + ‘汪汪汪~‘) def piao(self): print(‘不愛piao‘) obj1 = Dog(‘taotao‘) obj1.piao() ‘‘‘ 不愛piao ‘‘‘
6.3 繼承順序
6.3.1 無共同父類
class A: def f(self): print(‘A‘) class B: def f1(self): print(‘B‘) class C(A): def f(self): print(‘C‘) class D(B): def f1(self): print(‘D‘) class E(C, D): def f(self): print(‘E‘) obj1 = E() obj1.f1() ‘‘‘ D ‘‘‘
6.3.2 有共同父類
class Top: def f1(self): print(‘Top‘) class A(Top): def f(self): print(‘A‘) class B(Top): def f1(self): print(‘B‘) class C(A): def f(self): print(‘C‘) class D(B): def f1(self): print(‘D‘) class E(C, D): def f(self): print(‘E‘) obj1 = E() obj1.f1() ‘‘‘ D ‘‘‘
7.多態
Pyhon不支持Java和C#這一類強類型語言中多態的寫法,但是原生多態,其Python崇尚“鴨子類型”
1 1 class F1: 2 2 pass 3 3 4 4 5 5 class S1(F1): 6 6 7 7 def show(self): 8 8 print ‘S1.show‘ 9 9 10 10 11 11 class S2(F1): 12 12 13 13 def show(self): 14 14 print ‘S2.show‘ 15 15 16 16 17 17 # 由於在Java或C#中定義函數參數時,必須指定參數的類型 18 18 # 為了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類 19 19 # 而實際傳入的參數是:S1對象和S2對象 20 20 21 21 def Func(F1 obj): 22 22 """Func函數需要接收一個F1類型或者F1子類的類型""" 23 23 24 24 print obj.show() 25 25 26 26 s1_obj = S1() 27 27 Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show 28 28 29 29 s2_obj = S2() 30 30 Func(s2_obj) # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.showPython偽代碼實現Java或C#的多態
1 1 class F1: 2 2 pass 3 3 4 4 5 5 class S1(F1): 6 6 7 7 def show(self): 8 8 print ‘S1.show‘ 9 9 10 10 11 11 class S2(F1): 12 12 13 13 def show(self): 14 14 print ‘S2.show‘ 15 15 16 16 def Func(obj): 17 17 print obj.show() 18 18 19 19 s1_obj = S1() 20 20 Func(s1_obj) 21 21 22 22 s2_obj = S2() 23 23 Func(s2_obj)Python “鴨子類型”
8.經典問答
問題一:什麽樣的代碼才是面向對象?
答:從簡單來說,如果程序中的所有功能都是用 類 和 對象 來實現,那麽就是面向對象編程了。
問題二:函數式編程 和 面向對象 如何選擇?分別在什麽情況下使用?
答:須知:對於 C# 和 Java 程序員來說不存在這個問題,因為該兩門語言只支持面向對象編程(不支持函數式編程)。
而對於 Python 和 PHP 等語言卻同時支持兩種編程方式,且函數式編程能完成的操作,面向對象都可以實現;而面
向對象的能完成的操作,函數式編程不行(函數式編程無法實現面向對象的封裝功能)。
所以,一般在Python開發中,全部使用面向對象 或 面向對象和函數式混合使用
9.面對對象的應用場景
9.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
9.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‘)
面對對象基礎