http://www.cnblogs.com/linhaifeng/articles/8029564.html
类的类就为元类
元类所需知识
#exec() #参数1:字符串形式的命令 #参数2:全局作用域(字典形式),不指定默认使用全局globals() #参数3:局部作用域(字典形式),不指定默认使用局部locals() g={'x':1, 'y':2} l={} #把exec中代码当一个函数来看待 exec(""" global x,m x=10 m=100 z=3""",g,l) print(g) print(l)
一切皆对象,对象可以怎么来用,共性?
- 都可以被应用,x=obj
- 都可以当函数的参数传入
- 都可以当函数的返回值
- 都可以当作容器类型的元素,如都可当列表的元素
#类也是一个对象 class Foo: pass obj=Foo() print(type(obj)) print(type(Foo))
- 产生类的类称之为元类,默认所有用class定义的类,他们的元类是type
定义类的方式
#方式一定义类: class Chinese: country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name) #方式二定义类: #定义类的三要素 # 类名,类的基类,类的命名空间 class_name='Chinese' class_base=(object,) class_body=""" country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name) """ class_dic={} exec(class_body,globals(),class_dic) Chinese1=type(class_name,class_base,class_dic) print(Chinese) print(Chinese1)
自定义元类来控制类的创建
自己写一个元类
#自定义一个元类,因需要使用类中的其他方法,所以自定义元类继承于type class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): print(class_name)#打印类名字 print(class_bases)#打印类的基类 print(class_dic)#打印类的名称空间 super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法 #定义一个类,继承于自己定义的元类 class Chinese(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name)
对元类进行控制,以达到自定义
#自定义元类,控制类的行为 class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): #强制首字母大写 if not class_name.istitle(): raise TypeError("类名首字母必须大写") #强制写注释 if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError("类必须有注释,且不为空") print(class_dic) super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法 #定义一个类,继承于自己定义的元类 class chinese(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name)
#自定义元类,控制类的行为 class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): #强制首字母大写 if not class_name.istitle(): raise TypeError("类名首字母必须大写") #强制写注释 if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError("类必须有注释,且不为空") print(class_dic) super(Mymeta,self).__init__(class_name,class_bases,class_dic)#引用父类方法 #定义一个类,继承于自己定义的元类 class Chinese(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name)
自定义元类控制类实例化行为
知识储备__call__()
#知识储备__call__方法 class Foo: def __call__(self, *args, **kwargs): print(self) print(args) print(kwargs) obj=Foo() obj(1,2,3,a=4,b=5)
Foo默认继承元类,那么元类中则有一个__call__方法,会在调用Foo时会触发
Foo(1,2,3)等同于Foo.__call__(Foo,1,2,3)
自定义一个元类来控制类的实例化
#自定义元类,控制类的行为 class Mymeta(type): def __init__(self,class_name,class_bases,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): #1、制造一个空对象obj obj=object.__new__(self) #2、初始化obj self.__init__(obj,*args,**kwargs) #3、返回obj return obj #定义一个类,继承于自己定义的元类 class Chinese(object,metaclass=Mymeta): """中文人的类""" country='China' def __init__(self,name,age): self.name=name self.age=age def talks(self): print("%s is talking" % self.name) obj=Chinese('ya',18)#Chinese.__call__(Chinese,'ya,18) print(obj.__dict__)
验证创建是否成功
自定义元类控制类的实例化应用
单例模式
#单例模式,参数一样的对象就不要多次创建多次占用内存 class MySQL: def __init__(self): self.host='127.0.0.1' self.port=3306 obj1=MySQL() obj2=MySQL() obj3=MySQL() print(obj1) print(obj2) print(obj3)
单例模式的实现
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 def conn(self): pass def execute(self): pass obj1=MySQL.singleton() obj2=MySQL.singleton() obj3=MySQL.singleton() print(obj1) print(obj2) print(obj3)
通过元类来实现单例模式
#元类实现单例模式 class Mymeta(type): def __init__(self,class_name,class_bases,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)#继承父类方法 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): """ Mysql """ def __init__(self): self.host='127.0.0.1' self.port=3306 def conn(self): pass def execute(self): pass obj1=Mysql() obj2=Mysql() obj3=Mysql() print(obj1) print(obj2) print(obj3)