python 之 面向对象(元类、__call__、单例模式)
程序员文章站
2024-03-30 19:16:15
7.13 元类 元类:类的类就是元类,我们用class定义的类来产生我们自己的对象的,内置元类type是用来专门产生class定义的类 7.131 用内置的元类type,来实例化得到我们的类 7.132 __call__方法 在调用对象时自动触发__call__的执行 7.133 自定义元类来控制类 ......
7.13 元类
元类:类的类就是元类,我们用class定义的类来产生我们自己的对象的,内置元类type是用来专门产生class定义的类
code=""" global x x=0 y=2 """ #字符串内声明的名称是全局,其他为局部名称 global_dic={'x':100000} local_dic={} # 运行字符串内代码 exec(code,global_dic,local_dic) # 把全局名称空间的名称放入global_dic,把局部的放入local_dic print(global_dic) #{'x': 0} print(local_dic) #{'y': 2}
7.131 用内置的元类type,来实例化得到我们的类
class_name='chinese' class_bases=(object,) #基类 class_body=""" country="china" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def speak(self): print('%s speak chinese' %self.name) """ class_dic={} exec(class_body,{},class_dic) # 类的三大要素 print(class_name,class_bases,class_dic) # chinese (<class 'object'>,) {'country':'china', '__init__': <function __init__ at ...>, 'speak': <function speak at....>} chinese=type(class_name,class_bases,class_dic) #实例化一个类 print(chinese) #<class '__main__.chinese'> p=chinese('egon',18,'male') #实例化对象p print(p.name,p.age,p.sex) # egon 18 male #说明和class定义的类功能相同
7.132 __call__
方法
在调用对象时自动触发__call__
的执行
class foo: def __init__(self): pass def __call__(self, *args, **kwargs):# 调用对象,则会自动触发对象下的绑定方法__call__的执行, print('__call__',*args, **kwargs)# 然后将对象本身当作第一个参数传给self,将调用对象时括号内的值传给*args与**kwargs obj=foo() obj(1,2,3,a=1,b=2,c=3) #对象调用
7.133 自定义元类来控制类的创建行为
class mymeta(type): 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=mymeta('foo',(object,),class_dic) class foo(object,metaclass=mymeta): # metaclass=mymeta创建自定义元类 """ 文档注释 """
7.134 自定义元类来控制类的调用
控制类foo的调用过程,即控制实例化foo的过程
class mymeta(type): def __init__(self,class_name,class_bases,class_dic): #self=foo print(class_name) print(class_bases) print(class_dic) def __call__(self, *args, **kwargs): #self=foo,args=(1111,) 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) #<__main__.foo object at 0x000002019ee1bb70> print(obj.y) # 1111 print(obj.f1) #<bound method foo.f1 of <__main__.foo object at 0x000002019ee1bb70>> print(obj.x) # 1
7.14 单例模式
对于对象通过相同的配置文件进行实例化,可以使几个对象使用同一个内存地址,节省内存
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.singleton() # obj4=mysql(settings.ip,settings.port) obj5=mysql.singleton() obj6=mysql.singleton() print(obj4.ip,obj4.port) # 1.1.1.1 3306 print(obj4 is obj5 is obj6) # true
上一篇: PS怎么利用路径快速画出简单的花朵?
下一篇: async异步方法