• 2019.9.4学习内容及小结


    元类回顾

    type 只传一个参数时有什么用: 作用是打印对象的类型

    class 底层原理:通过type类来实例化得到类

    def __init__(self, name):
        self.name=name
    Person = type('Person', (object,), {'x':1, '__init__': __init__})
    p=Person('Nick')
    print(Person.__dict__)
    print(p.__dict__) #{'name': 'Nick'}
    print(p.name)#Nick
    等同于如下
    class Person(object):
        x = 1
        def __init__(self,name):
            self.name=name
    p=Person('Nick')
    print(Person.__dict__)
    print(p.__dict__)#{'name': 'Nick'}
    print(p.x)#1
    print(p.name)#Nick
    

    exec 执行字符串的代码,当成python解释器(就是把有一串字符串丢进去会被执行)

    ss='''
    x=1
    print(x)
    '''
    g={}
    l={}
    exec(ss, g, l)
    print(l)  #1 /{'x': 1} (把ss里面的字符串全部放在了l这个局部名称空间,打印执行l时先执行了字符串里面的(print(x)),再执行打印了(print(l))
    

    自定义元类:继承type

    # 自定义元类:继承type
    class Mymeta(type): #自定义元类必须继承type
        def __init__(self, name, bases, dic):
            #self是Person这个类对象(要创建的类名)
            #在这个位置,其实self也就说Person这个类,内部空间已经有东西了,名称空间里已经有东西了(Mymeta类实例化,会把Person的三个参数传到Mymeta的__init__方法中
            #所有这个地方可以通过dic来判断名称空间
            #也可以直接通过self.__dict__/self.属性 来判断
            a=dic.get('name')
            if not a:
                raise Exception('没有name属性,不能创建')
        # def __call__(self, *args,**kwargs):
        #     pass
    
    class Person(metaclass=Mymeta):  #Person=Mymeta('Person', (object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__中
        name='Nick'
    
        def __init__(self,age):
            self.age=age
            #raise Exception('就不让你创建')
    print(Person.__dict__)
    p=Person(18)
    print(p) #<__main__.Person object at 0x0000000009F82BA8>
    print(p.age) #18
    print(p.name) #Nick
     #注:如果在元类中定义了__call__,就必须有返回值(对象),否则无法生成对象
    # 总结:可以通过自定义元类,重写__init__方法来控制类的产生(重写__init__就是在元类的init下做一些设置(判断条件等))
    

    通过元类控制类的调用过程,实例化产生对象的过程

    # 通过元类控制类的调用过程,实例化产生对象的过程
    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            #该方法必须返回一个(类对象),这个地方返回什么,p=Person('lqz') p就是什么
    
            #返回一个真正的Person类对象
            #第一步:产生一个空对象
            object.__new__(self) #传一个参数,传类,就会产生一个该类的空对象(得到空对象obj)
            obj=object.__new__(self)
            #obj是Person的空对象
            #print(self.__new__ is object.__new__) #True
    
            #第二步:初始化该对象,把初始值放到对象中
            #obj是Person类的空对象  obj.__init__ 调用自己的绑定方法(Person下的init方法)
            obj.__init__(*args, **kwargs) #类的绑定方法
            #还可以类来调用
            #Person.__init__(obj, *args,**kwargs)
            #self.__init__(obj, *args,**kwargs) (self其实就是Person)
            return obj
    class Person(metaclass=Mymeta):
        def __init__(self,name):
            self.name=name
        def __call__(self,*args,**kwargs):
            print('xxx')
    p=Person('Nick')
    print(p.name) #Nick
    print(p) #<__main__.Person object at 0x00000000025F9710>
    # 原来的理解Person('Nick')会调用Person类的__init__的方法
    # 现在理解:这个位置会先调用元类的__call__方法,然后在__call__方法中调用了Person的__init__的方法,来完成对象的初始化
    p() #xxx  p()会调用Person的__call__方法
    

    模板:控制对象的产生模板

    class Mymeta(type):
    	def __call__(self, *args, **kwargs)
            obj=object.__new__(self)
            obj.__init__(*args,**kwargs)
            return obj
    class Person(metaclass=Mymmeta):
        def __init__(self, name)
        	self.name=namem
        def __call__(self, *args, **kwargs)
        	print('xxx')
    p=Person('Nick')   
    

    昨天的作业

    class Mymeta(type):
        def __call__(self,name,age):
            obj=object.__new__(self)
            obj.__dict__['attr']={'name':name,'age':age}
            return obj
    class Person(metaclass=Mymeta):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    p=Person('Nick',18)
    print(p.__dict__)
    print(p.attr['name']) #Nick
    

    赠送知识点

    class Person():
        def __init__(self,name,age):
            print('__init__')
            self.name=name
            self.age=age
        def __new__(cls, *args, **kwargs):
            print('__new__')
            #生成一个Person类的空对象
            return object.__new__(cls)
    p=Person('Nick',18)
    print(p) # <__main__.Person object at 0x000000000296F0B8>
    # 先执行__new__生成一个空对象,在执行__init__完成对象的初始化
    objcet.__new__ 传哪个类就得到哪个类的空对象
    p=object.__new__(Person)
    print(p)
    

    _ _new _ _ 和 _ _init _ _的区别

    # __new__ 创建空对象
    # __init__ 初始化空对象
    
    # object.__new__(Person) :生成Person类的对象  空的
    # type.__new__(cls, name, (object,),dic) : 生成cls这个类对象,里面是有东西的
    # 元类中
    # __init__:控制类的产生, 在__new__之后
    # __call__: 控制对象的产生
    # __new__ : 控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了
    
    class Mymeta(type):
        def __init__(self, name, bases, dic):
            #self是Person类,Person类中有名称空间之类的了
            print(name)
            print(bases)
            print(dic)
            pass
        def __new__(cls, name, bases, dic):
            #产生空对象(空类),在这里面生成的并不是空类,是有数据的类了
            #如何完成类的初始化,并且把name, basea,dic这些东西放入
            #return type.__new__(cls,name, bases,dic)
            dic2={'attr':{}}
            for k,v in dic.items():
                if not k.startswith('__'):
                    dic2['attr'][k]=v
            return type.__new__(cls,name, bases,dic2)
    class Person(metaclass=Mymeta):
        school='oldboy'
        age=18
        def __init__(self,name,age):
            self.name=name
            self.age=age
    print(Person.__dict__)
    print(Person.attr['school']) #oldboy
    

    单例

    实现单例的四种模式

    # #第一种方式(通过类的绑定方法)
    # class sql():
    #     _instance=None
    #     def __init__(self, port, host):
    #         self.port=port
    #         self.host=host
    #     @classmethod
    #     def get_sigoleton(cls):
    #         import settings
    #         if not cls._instance:
    #             cls._instance = cls(settings.PORT, settings.HOST)
    #         return cls._instance
    # s1=sql.get_sigoleton()
    # s2=sql.get_sigoleton()
    # print(s1)# <__main__.sql object at 0x00000000026A5FD0>
    # print(s2)#<__main__.sql object at 0x00000000026A5FD0>
    # s3=sql('33306','192.168.1.1')
    # print(s3)
    
    # #第二种方法:通过装饰器
    # def get_sigoleton(cls):
    #     _instance = None
    #     def wrapper(*args,**kwargs):
    #         if len(args)!=0 or len(kwargs)!=0:
    #             res=cls(*args, **kwargs)
    #             return res
    #         else:
    #             import settings
    #             nonlocal _instance
    #             if not _instance:
    #                 _instance=cls(settings.PORT,settings.HOST)
    #             return _instance
    #     return wrapper
    #
    # @get_sigoleton
    # class sql():
    #     def __init__(self,port,host):
    #         self.port=port
    #         self.host=host
    # s1=sql()
    # s2=sql()
    # print(s1)
    # print(s2)
    # s3=sql('33306','192.168.1.1')
    # print(s3)
    
    # # 第三种方式:通过元类
    # class Mymeta(type):
    #     def __init__(self, name,bases, dic):
    #         import settings
    #         self._instance=self(settings.PORT,settings.HOST)
    #     def __call__(self, *args, **kwargs):
    #         if len(args) != 0 or len(kwargs)!= 0:
    #             obj=object.__new__(self)
    #             obj.__init__(*args,**kwargs)
    #             return obj
    #         else:
    #             return self._instance
    # class sql(metaclass=Mymeta):
    #     def __init__(self, port, host):
    #         self.port=port
    #         self.host=host
    #
    # s1=sql()
    # s2=sql()
    # print(s1)
    # print(s2)
    # s3=sql('33306','192.168.1.1')
    # print(s3)
    
    # 第四种方式(通过模块导入)
    def test():
        from sigonleton import s1
        #print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import sql
    s2=sql('3306','192.168.1.1')
    print(s1)
    print(s2)
    
    
  • 相关阅读:
    apns libcurl
    apns libcurl
    epoll
    epoll
    Linux服务器压测
    Linux服务器压测
    libevent
    libevent
    shell脚本
    shell脚本
  • 原文地址:https://www.cnblogs.com/chmily/p/11469130.html
Copyright © 2020-2023  润新知