zoukankan      html  css  js  c++  java
  • 元类

    object是类的基类,type是类的元类

    type

    类的类

    class Foo:
        pass
    
    print(type(Foo))
    # <class 'type'>
    

    我们可以通过type来实例一个类,一个类创建的过程就是类的类被调用的过程

    def fn(self, name='world'): # 假如我们有一个函数叫fn
        print('Hello, %s.' % name)
        
    Hello = type('Hello', (object,), dict(say_hello=fn))  # 第一个参数是类名字,第二个参数是父类的集合,
    # 第三个参数是类的方法和属性的字典,键是属性或方法名,
    
    # 上面的写法就相当于
    class Hello():
        def say_hello(self, name='world'):
            print('Hello, %s.' % name)
    

    上面的类并没有声明自己的元类,默认就是type,

    class Moo(type):
        pass
    class Aoo():
        pass
    class Foo(metaclass=Moo):
        pass
    
    print(type(Moo))  # <class 'type'>
    print(type(Aoo))  # <class 'type'>
    print(type(Foo))  # <class '__main__.Moo'>
    

    另外还有很重要的一点,一个类继承了指定元类的类,那么这个类的元类就会是继承类的元类

    定义了metaclass的类的子类

    在python2中元类的定义时作为类的属性

    class Moo(type):
        pass
    
    class Foo():
        __metaclass__ = Moo
    

      当一个类继承了Foo时,会向上查找到__metaclass__属性,也就会由__metaclass__指定的类来实例类.

    在python3中虽然metaclass是由参数传递的,但他同样拥有这样的性质,一个类继承了指定metaclass的类,都会有指定的metaclass产生.

    class a(type):
        def __init__(self,*args,**kwarsg):
            print("造了个类")
            type.__init__(self,*args,**kwarsg)
    
    class c(metaclass=a): # 造了个类
        pass 
    class d(c):  # 造了个类
        pass
    class b(d):  # 造了个类
        pass

    我们也可以通过继承type来重写元类来控制类的产生

    自定义的元类也要接收三个参数

    同时也要了解一下类的一些方法:

    • __new__: 对象的创建,是一个静态方法。第一个參数是cls。(想想也是,不可能是self,对象还没创建,哪来的self)
    • __init__ : 对象的初始化, 是一个实例方法,第一个參数是self。
    • __call__ : 实例可call。注意不是类,是实例。
    先有创建,才有初始化。即先__new__,而后__init__。
    class Aoo():
        def __call__(self):
            return "haha"
    a = Aoo()
    print(a())
    
    # 哈哈哈

    一个简单实例

    class a(type):
        def __new__(cls, *args, **kwargs):
            print(args)  # ('b', (), {'__module__': '__main__', '__qualname__': 'b'})
            print(kwargs) # {}
            return type.__new__(cls, *args, **kwargs)
        def __init__(cls, name, bases, attrs):
            type.__init__(cls, name, bases, attrs)
            print("造了个类")
        def __call__(cls):
            type.__call__(cls)
            print("实例了个类")
    
    class b(metaclass=a): # 造了个类
        pass
    
    b() # 实例了个类

    根据__call__实现单例模式:

    既然类是元类的实例,那么类被实例化时就就执行了元类的__call__方法,我们可以根据这个来实现单例模式的类

    class Singleton(type):
        _instances = {}
        def __call__(cls, *args, **kwargs):  # 他的实例化出来的类实例化时调用了这个方法,
            if cls not in cls._instances:  
                # 如果这个来没有实例化对象,就去执行type的__call__方法,并且把实例存储在cls._instances中
                cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instances[cls]  # 返回实例
    
    class MyClass(metaclass=Singleton):
       pass
    
    a = MyClass()
    

    还可以

    MyClass = Singleton("MyClass",(object,),{"name":"pa"})
    a = MyClass()
    b = MyClass()
    print(a is b)
    # True
    

      更多方法我也不会

  • 相关阅读:
    蚂蚁变大象:浅谈常规网站是如何从小变大的(八)(转)
    蚂蚁变大象:浅谈常规网站是如何从小变大的(七)(转)
    蚂蚁变大象:浅谈常规网站是如何从小变大的(六)(转)
    蚂蚁变大象:浅谈常规网站是如何从小变大的(五)(转)
    蚂蚁变大象:浅谈常规网站是如何从小变大的(四)(转)
    蚂蚁变大象:浅谈常规网站是如何从小变大的(三)(转)
    简单的Poc Exp编写(上)
    kali渗透windowsXP过程
    [W3bSafe]Metasploit溢出渗透内网主机辅助脚本
    WannaCry勒索病毒全解读,权威修复指南大集合
  • 原文地址:https://www.cnblogs.com/wwg945/p/8536264.html
Copyright © 2011-2022 走看看