元類,__call__方法和單例模式
阿新 • • 發佈:2018-04-18
rom pan AR erro metaclass self acl clas HA
在python中一切皆對象的概念。
舉一個例子:
class Chinese: country=“china” def __init__(self, name,age,sex): self.name=name self.age=age self.sex=sex def change(self): print(‘%s speak Chinese ‘%self.name) #一切皆對象的原則。 那麽這個類Chinese也是對象,那麽他也有自己的類。那麽他的類就是type
元類:類的類就是元類。
我們用class定義類的使用來生產我們自己的對象的
內置元類type是用來專門產生class定義的類的
但是如何產生的呢?
用內置的元類type,來實例化得到我們的類
class_name=("Chinese") class_bases=(object,)#元組 class_boby=‘‘‘
country=“china”
def __init__(self, name,age,sex): self.name=name
self.age=age
self.sex=sex
def change(self):
print(‘%s speak Chinese ‘%self.name)
‘‘‘#類體代碼 type()#類名字 基類 和名稱空間
class_dic={}
exec(class_boby,{},class_dic)
print(class_dic)#產生了類的名稱空間
#類的三大要素湊齊了
print(class_name,class_bases,class_dic)
#實例化了
Chinese=type(class_name,class_bases,class_dic)
#print(Chinese)
p=Chinese(‘egon‘,18,‘male‘)
print(p.name,p.age,p.sex)
我們為毛要用這種方法來自定義類呢?
是因為這樣我們就了解了,類的底層原理,這樣就可以控制類的定了
##儲備知識__call__方法
class Foo: def __init__(self):#定義的時候自動觸發 pass def __str__(self):#在打印的時候自動觸發 pass def __del__(self):#在刪除的時候自動觸發 pass def __call__(self,*args,**kwargs):#在調用的時候自動觸發 print(”__call__“) obj=Foo() #怎麽調用? obj(1,2,3,x=1,y=2,z=3)
3、自定義元類:
class Mymeta(type): # # 來控制類Foo的創建 # def __init__(self,class_name,class_bases,class_dic): #self=Foo # # print(class_name) # # print(class_bases) # # print(class_dic) # if not class_name.istitle(): # raise TypeError(‘類名的首字母必須大寫傻叉‘) # # if not class_dic.get(‘__doc__‘): # raise TypeError(‘類中必須寫好文檔註釋,大傻叉‘) # # super(Mymeta,self).__init__(class_name,class_bases,class_dic) # # # 控制類Foo的調用過程,即控制實例化Foo的過程 # def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={} # # print(self) # # print(args) # # print(kwargs) # # #1 造一個空對象obj # obj=object.__new__(self) # # #2、調用Foo.__init__,將obj連同調用Foo括號內的參數一同傳給__init__ # self.__init__(obj,*args,**kwargs) # # return obj # # # # #Foo=Mymeta(‘Foo‘,(object,),class_dic) # class Foo(object,metaclass=Mymeta): # """ # 文檔註釋 # """ # x=1 # def __init__(self,y): # self.Y=y # # def f1(self): # print(‘from f1‘) # # # obj=Foo(1111) #Foo.__call__() # # # print(obj) # # print(obj.y) # # print(obj.f1) # # print(obj.x) # 單例模式 import settings class MySQL: __instance=None def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def singleton(cls): if not cls.__instance: obj=cls(settings.IP, settings.PORT) cls.__instance=obj return cls.__instance obj1=MySQL(‘1.1.1.2‘,3306) obj2=MySQL(‘1.1.1.3‘,3307) obj3=MySQL(‘1.1.1.4‘,3308) # obj4=MySQL(settings.IP,settings.PORT) # print(obj4.ip,obj4.port) obj4=MySQL.singleton() obj5=MySQL.singleton() obj6=MySQL.singleton() print(obj4 is obj5 is obj6)
元類,__call__方法和單例模式