元类
元类
python中一切皆对象,其类也是对象
对象的要求或者意义:
- 可以被引用,例如:x=obj
- 可以当作函数进行参数传入
- 可以作为容器类的元素
- 可以当作函数的返回值
1.元类的含义:产生类的类称之为元类,默认所有用class定义的类,他们的元类都是type
python中运用关键字class定义类的过程是:class(A) 其实就是 type实例化出来的,之后再由类实例化产生对象
2.定义类的两种形式
通过class关键字:class(Chinese) : #Chinese = type(...)
通过type: 定义出类的三要素:类的名称,类的基类,类的名称空间
3.自定义元类的应用
3.1可以控制类的具体行为
通过def __init__(self,class_name,class_bases,class_dic),获取到类的名称,类的基类,类的名称空间
之后运用class Chinese(object,metaclass=Mymeta) ,利用元类中的__init__来进行控制类名,类体的操作
def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名的首字母必须大写')
3.2可以控制类的实例化过程
通过def __call__(self,*args,**kwargs):进而得到对象的属性,
之后在进行三步操作:
- 创建空对象
- 初始化对象
- 返回对象值
def __call__(self, *args, **kwargs): #Chinese('egon',age=18) # print(self) #self=Chinese # print(args) #args=('egon',) # print(kwargs) #kwargs={'age':18} #第一件事: 造出一个空对象obj obj=object.__new__(self) #第二件事: 初始化obj self.__init__(obj,*args,**kwargs) #第三件事: 返回obj return obj
4.单例模式
运用python实现单例模式有两种方法:
1.定义一个绑定类的绑定方法
class MySQL: __instance = None def __init__(self): self.host='127.0.0.1' self.port=3306 @classmethod def singleton(cls): if not cls.__instance: obj = cls() cls.__instance=obj return cls.__instance
2.通过元类中的内置方法__call__来实现
class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): super(Mymeta,self).__init__(class_name,class_bases,class_dic) self.__instance=None def __call__(self, *args, **kwargs): #Chinese('egon',age=18) if not self.__instance: obj=object.__new__(self) self.__init__(obj) self.__instance=obj return self.__instance
# class Foo: # pass # f=Foo() # print(type(f)) # print(type(Foo)) # g={'x':1,'y':2} # l={} # exec(""" # global x,m # x=10 # m=100 # z=3 # """,g,l) # print(g) # print(l) # ------------------------- # 产生类得第一种方式: class Chinese: country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking'%self.name) # obj=Chinese('alice',12) # obj.talk() # print(obj.name,obj.age) #产生类得第二种方式: class_name='Chinese' class_base=(object,) class_body=""" country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking'%self.name) """ # class_dic={} # exec(class_body,globals(),class_dic) # # print(class_dic) # ch = type(class_name,class_base,class_dic) # obj1=ch('alice',12) # print(obj1.__dict__) # print(ch.__dict__) # print(ch) # print(obj1,obj1.name,obj1.age) #自定义元类 控制类的行为: class Mymeta(type): #元类 # print('--1--') def __init__(self,class_name,class_bases,class_dic): # 控制类的创建 # print(class_name) # print(class_bases) # print(class_dic) if not class_name.istitle(): raise TypeError('类名的首字母必须大写') if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释,且注释不能为空') super(Mymeta, self).__init__(class_name,class_bases,class_dic) def __call__(self, *args, **kwargs): # 控制类的实例化 # print(self) # print(args) # print(kwargs) obj=object.__new__(self) #1.造空对象 self.__init__(obj,*args,**kwargs) #2.初始化obj return obj #返回obj class Chinese(object,metaclass=Mymeta): ''' 中文人的类 ''' country='China' def __init__(self,name,age): print('--2--') self.name=name self.age=age def talk(self): print('%s is talking'%self.name) def __call__(self, *args, **kwargs): print(self) print(args) print(kwargs) # obj=Chinese('alice',12) # 触发它的类的 __call__() 元类 # obj(1,2,3,a=1,b=2) # 触发它的类的 __call__() Chinese # print(obj.__dict__) # print(Chinese.__dict__) # # print(type(Chinese)) # Chinese=Mymeta(class_name,class_bases,class_dir) # print(obj.__dict__) #自定义元类的应用: # obj1=int(1) # obj2=int(1) # print(id(obj1)) # print(id(obj2)) # print(obj1 is obj2) # 实现了单例模式 参数相同 多个对象 使用同一块内存 是一种优化策略 # 单例模式 实现方式一: class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): super().__init__(class_name,class_bases,class_dic) self.__instance=None def __call__(self, *args, **kwargs): if not self.__instance: obj = object.__new__(self) self.__init__(obj) self.__instance=obj return self.__instance class Mysql(object,metaclass=Mymeta): # __instance=None def __init__(self): self.host='127.0.0.1' self.port=3306 # @classmethod # def singleton(cls): # if not cls.__instance: # obj=cls() # cls.__instance=obj # return cls.__instance def conn(self): pass def execute(self): pass # obj1=Mysql() # obj2=Mysql() # print(obj2.__dict__) # print(id(obj1)) # print(id(obj2)) # obj1=Mysql.singleton() # obj2=Mysql.singleton() # # print(obj1.__dict__) # print(id(obj1)) # print(id(obj2)) # obj1=Mysql() # obj2=Mysql() # print(id(obj1)) # print(id(obj2))