本篇內容:
- 1、反射
- 2、面向對象編程
- 3、面向對象三大特性
- 4、類成員
- 5、類成員修飾符
- 6、類的特殊成員
- 7、單例模式
反射
python中的反射功能是由以下四個內置函數提供:hasattr、getattr、setattr、delattr,改四個函數分別用於對對象內部執行:檢查是否含有某成員、獲取成員、設置成員、刪除成員。
import commas同等於下面字符串導入模塊 inp = input("請輸入模塊名:") dd = __import__(inp) ret =dd.f1() print(ret)
#應用根據用戶輸入導入模塊
inp = input("請輸入模塊:") inp_func = input("請輸入執行的函數:") # __import__以字符串的形式導入模塊
moudle = __import__(inp) #getattr 用以去某個模塊中尋找某個函數
target_func = getattr(moudle,inp_func) relust = target_func() print(relust)
1、getattr
通過字符串的形式去某個模塊中尋找東西
import commas #去commas,尋找name變量,找不到返回none
target_func = getattr(commas ,"name",None) print(target_func)
2、hasattr
通過字符串的形式去某個模塊中判斷東西是否存在
import commas #去commas模塊中尋找f1,有返回true,沒有返回none
target_func = hasattr(commas,"f1") print(target_func)
3、setattr
通過字符串的形式去某個模塊中設置東西
import commas #去commas模塊中尋找name,有返回true,沒有返回none
target_func1 = hasattr(commas,"name") print(target_func1) #在內存里往commas模塊中添加name = "zhangyanlin"
setattr(commas,"name","zhangyanlin") #在內存里往commas模塊中創建函數
setattr(commas,"f3",lambda x: "zhen" if x >10 else "jia") #去commas模塊中尋找name,有返回true,沒有返回none
target_func = hasattr(commas,"name") print(target_func)
4、delattr
import commas target_func = hasattr(commas,"f1") print(target_func) del_func = delattr(commas,"f1") target_func = hasattr(commas,"f1") print(target_func)
案例:
''' 基於web框架實現路由功能 ''' url = str(input("請輸入URL:")) #輸入URL,先輸入模塊,后面加函數 target_moudle,target_func = url.split("/") # 用/把分割開,前面是模塊 后面是函數 moudle = __import__(target_moudle,fromlist=True) #導入模塊 if hasattr(moudle,target_func): #判斷模塊里有這個函數 target_func = getattr(moudle,target_func) #找到那個函數 ret = target_func() #執行函數 print(ret) else: #否則報錯 print("404")
class Foo: def __init__(self,name): self.name = name def login(self): print("登錄請按1:") obj = Foo("zhangyanlin") ret = getattr(obj,"name") print(ret) #反射 #以字符串的形式去對續航中操作成員 #反射:類,只能找類的成員 ret = hasattr(Foo,"login") print(ret) #反射:對象,既可以找對象也能找類的成員 ret = hasattr(obj,"name") print(ret) ret = hasattr(obj,"login") print(ret)
面向對象編程
- 面向過程:根據業務邏輯從上到下寫壘代碼
- 函數式:將某功能代碼封裝到函數中,日后便無需重復編寫,僅調用函數即可
- 面向對象:對函數進行分類和封裝,讓開發“更快更好更強...”
面向過程編程最易被初學者接受,其往往用一長段代碼來實現指定功能,開發過程中最常見的操作就是粘貼復制,即:將之前實現的代碼塊復制到現需功能處。
1、創建類和對象
面向對象編程是一種編程方式,此編程方式的落地需要使用 “類” 和 “對象” 來實現,所以,面向對象編程其實就是對 “類” 和 “對象” 的使用。
類就是一個模板,模板里可以包含多個函數,函數里實現一些功能
對象則是根據模板創建的實例,通過實例對象可以執行類中的函數

- class是關鍵字,表示類
- 創建對象,類名稱后加括號即可
# 創建類
class Foo:
def Bar(self):
print 'Bar'
def Hello(self, name):
print 'i am %s' %name
# 根據類Foo創建對象obj
obj = Foo()
obj.Bar() #執行Bar方法
obj.Hello('wupeiqi') #執行Hello方法
一、封裝
封裝,顧名思義就是將內容封裝到某個地方,以后再去調用被封裝在某處的內容。所以,在使用面向對象的封裝特性時,需要:
- 將內容封裝到某處
- 從某處調用被封裝的內容
第一步:將內容封裝到某處

demo
第二步:從某處調用被封裝的內容調用被封裝的內容時,有兩種情況:
- 通過對象直接調用
- 通過self間接調用
1、通過對象直接調用被封裝的內容上圖展示了對象 obj1 和 obj2 在內存中保存的方式,根據保存格式可以如此調用被封裝的內容:對象.屬性名

class Foo: def __init__(self, name, age): self.name = name self.age = age obj1 = Foo('張岩林', 18) print(obj1.name) # 直接調用obj1對象的name屬性
print(obj1.age) # 直接調用obj1對象的age屬性
obj2 = Foo('Aylin', 18) print(obj2.name) # 直接調用obj2對象的name屬性
print(obj2.age ) # 直接調用obj2對象的age屬性
demo 2、通過self間接調用被封裝的內容執行類中的方法時,需要通過self間接調用被封裝的內容
class Foo: def __init__(self,backend): '''構造方法''' self.backend = backend #普通字段
self.auther = "張岩林"
def feach(self): print(self.backend,"作者:",self.auther) def add(self): print(self.backend,"作者:",self.auther) #創建對象並把www.baidu.com封裝到對象中
obj = Foo("www.baidu.com") obj.feach() obj1 = Foo("www.google.com") obj1.add()
demo 二、繼承繼承,面向對象中的繼承和現實生活中的繼承相同,即:子可以繼承父的內容。例如: 貓可以:喵喵叫、吃、喝、拉、撒 狗可以:汪汪叫、吃、喝、拉、撒吃、喝、拉、撒是貓和狗都具有的功能,而我們卻分別的貓和狗的類中編寫了兩次。如果使用 繼承 的思想,如下實現: 動物:吃、喝、拉、撒 貓:喵喵叫(貓繼承動物的功能) 狗:汪汪叫(狗繼承動物的功能)
#繼承實例
class Animals: def chi(self): print(self.name+"吃") def he(self): print(self.name+"喝") def la(self): print(self.name+"拉") def jiao(self): print("叫叫") class Uncle: def jiao(self): print("叫叫叫") class dog(Animals,Uncle): def __init__(self,name): self.name = name def jiao(self): print("叫") ddog = dog("狗") ddog.chi() ddog.jiao()
demo所以,對於面向對象的繼承來說,其實就是將多個類共有的方法提取到父類中,子類僅需繼承父類而不必一一實現每個方法。注:除了子類和父類的稱謂,你可能看到過 派生類 和 基類 ,他們與子類和父類只是叫法不同而已。
那么問題又來了,多繼承呢?
- 是否可以繼承多個類
- 如果繼承的多個類每個類中都定了相同的函數,那么那一個會被使用呢?
1、Python的類可以繼承多個類,Java和C#中則只能繼承一個類 

class Zhang(object): def f1(self): print("zhang") class A(Zhang): def f(self): print("A") class B(A): def f(self): print("B") class C(Zhang): def f1(self): print("C") class D(C): def f(self): print("D") class E(D,B): def f(self): print("E") ret = E() ret.f1()
demo 三、多態 Pyhon不支持多態並且也用不到多態,多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚“鴨子類型”。
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
python偽代碼實現java,c#多態
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)
python“鴨子類型” 類成員 1、字段:
靜態字段:提供給類里每個對象(方法)使用
普通字段:讓每個方法都有不同的數據
2、方法:
靜態方法: 無需使用對象封裝,用類方法執行
類方法: 類方法執行,調用時會顯示出當前是哪個類
普通方法: 對象方式執行,使用對象中的數據
3、特性:
可以獲取特性 也可以設置特性
一、字段字段包括:普通字段和靜態字段,他們在定義和使用中有所區別,而最本質的區別是內存中保存的位置不同,
- 普通字段屬於對象
- 靜態字段屬於類

class Province: # 靜態字段 country = '中國' def __init__(self, name): # 普通字段 self.name = name # 直接訪問普通字段 obj = Province('河北省') print(obj.name) # 直接訪問靜態字段 Province.country
View Code由上述代碼可以看出【普通字段需要通過對象來訪問】【靜態字段通過類訪問】,在使用上可以看出普通字段和靜態字段的歸屬是不同的。其在內容的存儲方式類似如下圖:
注:靜態字段只在內存中保存一份,普通字段在每個對象中都要保存一份 二、方法方法包括:普通方法、靜態方法和類方法,三種方法在內存中都歸屬於類,區別在於調用方式不同。 1、普通方法:由對象調用;至少一個self參數;執行普通方法時,自動將調用該方法的對象賦值給self; 2、類方法:由類調用; 至少一個cls參數;執行類方法時,自動將調用該方法的類復制給cls; 3、靜態方法:由類調用;無默認參數;
class Foo: def __init__(self, name): self.name = name def ord_func(self): """ 定義普通方法,至少有一個self參數 """ # print self.name print('普通方法') @classmethod def class_func(cls): """ 定義類方法,至少有一個cls參數 """ print('類方法') @staticmethod def static_func(): """ 定義靜態方法 ,無默認參數""" print('靜態方法') # 調用普通方法 f = Foo() f.ord_func() # 調用類方法 Foo.class_func() # 調用靜態方法 Foo.static_func()
定義方法並使用
相同點:對於所有的方法而言,均屬於類(非對象)中,所以,在內存中也只保存一份。不同點:方法調用者不同、調用方法時自動傳入的參數不同。 三、特性 如果你已經了解Python類中的方法,那么特性就非常簡單了,因為Python中的屬性其實是普通方法的變種。對於特性,有以下兩個知識點: 1、特性的基本使用 2、特性的兩種定義方式 1、特性的基本使用
# ############### 定義 ############### class Foo: def func(self): pass # 定義特性 @property def prop(self): pass # ############### 調用 ############### foo_obj = Foo() foo_obj.func() foo_obj.prop #調用屬性
特性
由屬性的定義和調用要注意一下幾點: 1、定義時,在普通方法的基礎上添加 @property 裝飾器; 2、定義時,屬性僅有一個self參數 3、調用時,無需括號
方法:foo_obj.func()
屬性:foo_obj.prop注意:屬性存在意義是:訪問屬性時可以制造出和訪問字段完全相同的假象 屬性由方法變種而來,如果Python中沒有屬性,方法完全可以代替其功能。實例:對於主機列表頁面,每次請求不可能把數據庫中的所有內容都顯示到頁面上,而是通過分頁的功能局部顯示,所以在向數據庫中請求數據時就要顯示的指定獲取從第m條到第n條的所有數據(即:limit m,n),這個分頁的功能包括: 1、根據用戶請求的當前頁和總數據條數計算出 m 和 n 2、根據m 和 n 去數據庫中請求數據 
# ############### 定義 ############### class Pager: def __init__(self, current_page): # 用戶當前請求的頁碼(第一頁、第二頁...) self.current_page = current_page # 每頁默認顯示10條數據 self.per_items = 10 @property def start(self): val = (self.current_page - 1) * self.per_items return val @property def end(self): val = self.current_page * self.per_items return val # ############### 調用 ############### p = Pager(1) p.start 就是起始值,即:m p.end 就是結束值,即:n
View Code 2、屬性的兩種定義方式屬性的定義有兩種方式: 1、裝飾器 即:在方法上應用裝飾器 2、靜態字段 即:在類中定義值為property對象的靜態字段 1.1 裝飾器方式經典類,具有一種@property裝飾器
# ############### 定義 ############### class Goods: @property def price(self): return "張岩林" # ############### 調用 ############### obj = Goods() result = obj.price # 自動執行 @property 修飾的 price 方法,並獲取方法的返回值
View Code新式類,具有三種@property裝飾器
# ############### 定義 ############### class Goods(object): @property def price(self): print('@property') @price.setter def price(self, value): print('@price.setter') @price.deleter def price(self): print('@price.deleter') # ############### 調用 ############### obj = Goods() obj.price # 自動執行 @property 修飾的 price 方法,並獲取方法的返回值 obj.price = 123 # 自動執行 @price.setter 修飾的 price 方法,並將 123 賦值給方法的參數 del obj.price # 自動執行 @price.deleter 修飾的 price 方法
View Code注:1、經典類中的屬性只有一種訪問方式,其對應被 @property 修飾的方法
2、新式類中的屬性有三種訪問方式,並分別對應了三個被@property、@方法名.setter、@方法名.deleter修飾的方法由於新式類中具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除
class Goods(object): def __init__(self): # 原價 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 實際價格 = 原價 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): self.original_price = value @price.deltter def price(self, value): del self.original_price obj = Goods() obj.price # 獲取商品價格 obj.price = 200 # 修改商品原價 del obj.price # 刪除商品原價
View Code 1.2 靜態字段方式,創建值為property對象的靜態字段當使用靜態字段的方式創建屬性時,經典類和新式類無區別
class Foo: def get_bar(self): return '張岩林' BAR = property(get_bar) obj = Foo() reuslt = obj.BAR # 自動調用get_bar方法,並獲取方法的返回值 print(reuslt)
View Codeproperty的構造方法中有個四個參數 1、第一個參數是方法名,調用 對象.屬性 時自動觸發執行方法 2、第二個參數是方法名,調用 對象.屬性 = XXX 時自動觸發執行方法 3、第三個參數是方法名,調用 del 對象.屬性 時自動觸發執行方法 4、第四個參數是字符串,調用 對象.屬性.__doc__ ,此參數是該屬性的描述信息
class Foo: def get_bar(self): return 'zhangyanlin' # *必須兩個參數 def set_bar(self, value): return return 'set value' + value def del_bar(self): return "張岩林" BAR = property(get_bar, set_bar, del_bar, 'description...') obj = Foo() obj.BAR # 自動調用第一個參數中定義的方法:get_bar obj.BAR = "aylin" # 自動調用第二個參數中定義的方法:set_bar方法,並將“aylin”當作參數傳入 del Foo.BAR # 自動調用第三個參數中定義的方法:del_bar方法 obj.BAE.__doc__ # 自動獲取第四個參數中設置的值:description...
View Code由於靜態字段方式創建屬性具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除
class Goods(object): def __init__(self): # 原價 self.original_price = 100 # 折扣 self.discount = 0.8 def get_price(self): # 實際價格 = 原價 * 折扣 new_price = self.original_price * self.discount return new_price def set_price(self, value): self.original_price = value def del_price(self, value): del self.original_price PRICE = property(get_price, set_price, del_price, '價格屬性描述...') obj = Goods() obj.PRICE # 獲取商品價格 obj.PRICE = 200 # 修改商品原價 del obj.PRICE # 刪除商品原價
View Code所以,定義屬性共有兩種方式,分別是【裝飾器】和【靜態字段】,而【裝飾器】方式針對經典類和新式類又有所不同。 類成員修飾符 類的所有成員在上一步驟中已經做了詳細的介紹,對於每一個類的成員而言都有兩種形式: 1、公有成員,在任何地方都能訪問 2、私有成員,只有在類的內部才能方法 私有成員和公有成員的定義不同:私有成員命名時,前兩個字符是下划線。(特殊成員除外,例如:__init__、__call__、__dict__等)
class C:
def __init__(self):
self.name = '公有字段'
self.__foo = "私有字段"
私有成員和公有成員的訪問限制不同: 1、靜態字段 1、公有靜態字段:類可以訪問;類內部可以訪問;派生類中可以訪問 2、私有靜態字段:僅類內部可以訪問;
class C: name = "公有靜態字段" def func(self): print(C.name) class D(C): def show(self): print(C.name) C.name # 類訪問 obj = C() obj.func() # 類內部可以訪問 obj_son = D() obj_son.show() # 派生類中可以訪問
公有字段
class C: __name = "公有靜態字段" def func(self): print(C.__name) class D(C): def show(self): print(C.__name) C.__name # 類訪問 ==> 錯誤 obj = C() obj.func() # 類內部可以訪問 ==> 正確 obj_son = D() obj_son.show() # 派生類中可以訪問 ==> 錯誤
私有字段2、普通字段 1、公有普通字段:對象可以訪問;類內部可以訪問;派生類中可以訪問 2、私有普通字段:僅類內部可以訪問;注:如果想要強制訪問私有字段,可以通過 【對象._類名__私有字段明 】訪問(如:obj._C__foo),不建議強制訪問私有成員。 
class C: def __init__(self): self.foo = "公有字段" def func(self): print(self.foo) # 類內部訪問 class D(C): def show(self): print(self.foo) # 派生類中訪問 obj = C() obj.foo # 通過對象訪問 obj.func() # 類內部訪問 obj_son = D(); obj_son.show() # 派生類中訪問
公有字段
class C: def __init__(self): self.__foo = "私有字段" def func(self): print(self.foo ) # 類內部訪問 class D(C): def show(self): print(self.foo) # 派生類中訪問 obj = C() obj.__foo # 通過對象訪問 ==> 錯誤 obj.func() # 類內部訪問 ==> 正確 obj_son = D(); obj_son.show() # 派生類中訪問 ==> 錯誤
私有字段 類的特殊成員 1、 __doc__ 表示類的描述信息
class Foo: """ 描述類信息,這是用於看片的神奇 """ def func(self): pass print Foo.__doc__ #輸出:類的描述信息
View Code2、 __module__ 和 __class__ __module__ 表示當前操作的對象在那個模塊 __class__ 表示當前操作的對象的類是什么
#!/usr/bin/env python # -*- coding:utf-8 -*- class C: def __init__(self): self.name = 'zhangyanlin'
lib/test.py
from lib.test import C obj = C() print obj.__module__ # 輸出 lib.aa,即:輸出模塊 print obj.__class__ # 輸出 lib.aa.C,即:輸出類
index3、 __init__ 構造方法,通過類創建對象時,自動觸發執行。 
class Foo: def __init__(self, name): self.name = name self.age = 18 obj = Foo('張岩林') # 自動執行類中的 __init__ 方法
View Code
class Annimal: def __init__(self): print("動物構造方法") self.name = "動物" class Dog(Annimal): def __init__(self): print("狗狗構造方法") self.nn = "狗" super(Dog,self).__init__() # Annimal.__init__(self) d = Dog() print(d.__dict__)
繼承父類__init__ 4、 __del__ 析構方法,當對象在內存中被釋放時,自動觸發執行。注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。 
class Foo: def __del__(self): pass
code 5、 __call__ 對象后面加括號,觸發執行。注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print (__call__) obj = Foo() # 執行 __init__ obj() # 執行 __call__
View Code6、 __dict__ 類或對象中的所有成員上文中我們知道:類的普通字段屬於對象;類中的靜態字段和方法等屬於類,即:
class Province: country = 'China' def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print 'func' # 獲取類的成員,即:靜態字段、方法、 print Province.__dict__ # 輸出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None} obj1 = Province('HeBei',10000) print obj1.__dict__ # 獲取 對象obj1 的成員 # 輸出:{'count': 10000, 'name': 'HeBei'} obj2 = Province('HeNan', 3888) print obj2.__dict__ # 獲取 對象obj1 的成員 # 輸出:{'count': 3888, 'name': 'HeNan'}
View Code7、 __str__如果一個類中定義了__str__方法,那么在打印 對象 時,默認輸出該方法的返回值。
class Foo: def __str__(self): return 'zhangyanlin' obj = Foo() print(obj) # 輸出:zhangyanlin
View Code8、__getitem__、__setitem__、__delitem__用於索引操作,如字典。以上分別表示獲取、設置、刪除數據
class Foo: def __getitem__(self, item): # 獲取 print(item) def __setitem__(self, key, value): # 設置 print(key,value) def __delitem__(self, key): # 刪除 print(key) obj = Foo() obj["張岩林"] # 調用getitem obj["name"]=1234 # 調用setitem del obj["namename"] # 調用delitem print(Foo.__dict__)
View Code9、 __iter__ 用於迭代器,之所以列表、字典、元組可以進行for循環,是因為類型內部定義了 __iter__ 
#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __init__(self, sq): self.sq = sq def __iter__(self): return iter(self.sq) obj = Foo([11,22,33,44]) for i in obj: print i
View Code
#!/usr/bin/env python # -*- coding:utf-8 -*- obj = iter([11,22,33,44]) while True: val = obj.next() print(val)
for循環內部語法 單例模式 所謂單例,是指一個類的實例從始至終只能被創建一次。 方法1如果想使得某個類從始至終最多只有一個實例,使用__new__方法會很簡單。Python中類是通過__new__來創建實例的:
class Singleton(object):
def __new__(cls,*args,**kwargs):
if not hasattr(cls,'_inst'):
cls._inst=super(Singleton,cls).__new__(cls,*args,**kwargs)
return cls._inst
if __name__=='__main__':
class A(Singleton):
def __init__(self,s):
self.s=s
a=A('apple')
b=A('banana')
print(id(a),a.s)
print(id(b),b.s)
結果:
29922256 banana 29922256 banana
通過__new__方法,將類的實例在創建的時候綁定到類屬性_inst上。如果cls._inst為None,說明類還未實例化,實例化並將實例綁定到cls._inst,以后每次實例化的時候都返回第一次實例化創建的實例。注意從Singleton派生子類的時候,不要重載__new__。 方法2當你編寫一個類的時候,某種機制會使用類名字,基類元組,類字典來創建一個類對象。新型類中這種機制默認為type,而且這種機制是可編程的,稱為元類__metaclass__ 。
class Singleton(type):
def __init__(self,name,bases,class_dict):
super(Singleton,self).__init__(name,bases,class_dict)
self._instance=None
def __call__(self,*args,**kwargs):
if self._instance is None:
self._instance=super(Singleton,self).__call__(*args,**kwargs)
return self._instance
if __name__=='__main__':
class A(object):
__metaclass__=Singleton
a=A()
b=A()
print(id(a),id(b))
結果:
34248016 34248016
id是相同的。例子中我們構造了一個Singleton元類,並使用__call__方法使其能夠模擬函數的行為。構造類A時,將其元類設為Singleton,那么創建類對象A時,行為發生如下:A=Singleton(name,bases,class_dict),A其實為Singleton類的一個實例。創建A的實例時,A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(),這樣就將A的所有實例都指向了A的屬性_instance上,這種方法與方法1其實是相同的。 方法4最簡單的方法:
class singleton(object):
pass
singleton=singleton()
將名字singleton綁定到實例上,singleton就是它自己類的唯一對象了。 方法5
class ConnectionPool:
__instance = None
def __init__(self):
self.ip = "192.168.1.1"
self.port = 3306
self.username = "zhangyanlin"
self.pwd = 123456
@staticmethod
def get_instance():
if ConnectionPool.__instance:
return ConnectionPool.__instance
else:
ConnectionPool.__instance = ConnectionPool()
return ConnectionPool.__instance
obj1 = ConnectionPool()
print(obj1.get_instance())
obj2 = ConnectionPool()
print(obj2.get_instance())
obj3 = ConnectionPool()
print(obj3.get_instance())
定義靜態方法,判斷讓所有只用第一個對象在內存中創建的ID

