更新時(shí)間:2018-07-13 來源:黑馬程序員JavaEE培訓(xùn)學(xué)院 瀏覽量:
Python中的類也是對(duì)象。元類就是用來創(chuàng)建這些類(對(duì)象)的,元類就是類的類,你可以這樣理解為:
MyClass = MetaClass() #元類創(chuàng)建
MyObject = MyClass() #類創(chuàng)建實(shí)例
實(shí)際上MyClass就是通過type()來創(chuàng)創(chuàng)建出MyClass類,它是type()類的一個(gè)實(shí)例;同時(shí)MyClass本身也是類,也可以創(chuàng)建出自己的實(shí)例,這里就是MyObject
函數(shù)type實(shí)際上是一個(gè)元類。type就是Python在背后用來創(chuàng)建所有類的元類?,F(xiàn)在你想知道那為什么type會(huì)全部采用小寫形式而不是Type呢?好吧,我猜這是為了和str保持一致性,str是用來創(chuàng)建字符串對(duì)象的類,而int是用來創(chuàng)建整數(shù)對(duì)象的類。type就是創(chuàng)建類對(duì)象的類。你可以通過檢查__class__屬性來看到這一點(diǎn)。Python中所有的東西,注意,我是指所有的東西——都是對(duì)象。這包括整數(shù)、字符串、函數(shù)以及類。它們?nèi)慷际菍?duì)象,而且它們都是從一個(gè)類創(chuàng)建而來。
那什么是單例呢?為什么我們要用單例設(shè)計(jì)模式?
我們首先來看看單例模式的使用場(chǎng)景,然后再來分析為什么需要單例模式。
? Python的logger就是一個(gè)單例模式,用以日志記錄
? Windows的資源管理器是一個(gè)單例模式
? 線程池,數(shù)據(jù)庫(kù)連接池等資源池一般也用單例模式
? 網(wǎng)站計(jì)數(shù)器
從這些使用場(chǎng)景我們可以總結(jié)下什么情況下需要單例模式:
1. 當(dāng)每個(gè)實(shí)例都會(huì)占用資源,而且實(shí)例初始化會(huì)影響性能,這個(gè)時(shí)候就可以考慮使用單例模式,它給我們帶來的好處是只有一個(gè)實(shí)例占用資源,并且只需初始化一次;
2. 當(dāng)有同步需要的時(shí)候,可以通過一個(gè)實(shí)例來進(jìn)行同步控制,比如對(duì)某個(gè)共享文件(如日志文件)的控制,對(duì)計(jì)數(shù)器的同步控制等,這種情況下由于只有一個(gè)實(shí)例,所以不用擔(dān)心同步問題。
那什么是單例呢?為什么我們要用單例設(shè)計(jì)模式?
我們首先來看看單例模式的使用場(chǎng)景,然后再來分析為什么需要單例模式。
? Python的logger就是一個(gè)單例模式,用以日志記錄
? Windows的資源管理器是一個(gè)單例模式
? 線程池,數(shù)據(jù)庫(kù)連接池等資源池一般也用單例模式
? 網(wǎng)站計(jì)數(shù)器
從這些使用場(chǎng)景我們可以總結(jié)下什么情況下需要單例模式:
1. 當(dāng)每個(gè)實(shí)例都會(huì)占用資源,而且實(shí)例初始化會(huì)影響性能,這個(gè)時(shí)候就可以考慮使用單例模式,它給我們帶來的好處是只有一個(gè)實(shí)例占用資源,并且只需初始化一次;
2. 當(dāng)有同步需要的時(shí)候,可以通過一個(gè)實(shí)例來進(jìn)行同步控制,比如對(duì)某個(gè)共享文件(如日志文件)的控制,對(duì)計(jì)數(shù)器的同步控制等,這種情況下由于只有一個(gè)實(shí)例,所以不用擔(dān)心同步問題。
在python中實(shí)現(xiàn)單例模式有幾種方法:
1. 使用模塊
2. 使用裝飾器
3. 使用類
4. 基于__new__方法實(shí)現(xiàn)(推薦使用,方便)
5. 基于metaclass元類方式實(shí)現(xiàn)
這里說說基于元類來實(shí)現(xiàn)。代碼如下:
class Singleton(type):
def __init__(cls, name, bases, dic):
print('元類的__init__方法在被執(zhí)行')
super(Singleton, cls).__init__(name, bases, dic)
cls.instance = None
def __call__(cls, *args, **kwargs):
if not cls.instance:
print('創(chuàng)建一個(gè)新對(duì)象')
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
else:
print('單例,只能創(chuàng)建一個(gè)對(duì)象')
return cls.instance
class A(metaclass=Singleton):
# __metaclass__ = Singleton
pass # python3 取消了__metaclass__屬性
a = A()
b = A()
print(a is b)
print(A.__dict__)
元類的__init__方法在被執(zhí)行
創(chuàng)建一個(gè)新對(duì)象
單例,只能創(chuàng)建一個(gè)對(duì)象
True
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, 'instance': <__main__.A object at 0x1027c5cf8>}
本文版權(quán)歸黑馬程序員JavaEE學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
首發(fā):http://java.itheima.com/