欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python 之 面向对象(元类、__call__、单例模式)

程序员文章站 2023-04-05 13:49:26
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