1. 程式人生 > >元類,__call__方法和單例模式

元類,__call__方法和單例模式

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__方法和單例模式