zoukankan      html  css  js  c++  java
  • type和metaclass元类

    元类type

    1. 创建类的两种方式 (都是由type元类创建)

    方式一:

    class Foo(object):      # 默认metaclass = type, 当前类, 由type类创建
        a = 'aaa'
        def func(self, x):
            return x + 1

    方式二:

    Foo = type("Foo", (object, ), {'a': "aaa", 'func': lambda self, x: x + 1})

    metaclass(元类)

    作用:
      通过metaclass可以指定当前类由哪一个元类创建

    python2和python3的区别:

        python3:
            class Foo(object, metaclass=type):    
                pass
    
        python2:
            class Foo(object):
                __metaclass__=type    
                pass

    自定义元类

    1、第一步

    class MyType(type):
        def __init__(self, *args, **kwargs):
            print("创建类之前")
            super(MyType, self).__init__(*args, **kwargs)
            print("创建类之后")

    2、第二步

    class Base(object, metaclass=MyType):
        pass

    Base = MyType('Base', (object, ), {})

    这两部代码写完后,执行:

    输出:

      创建类之前
      创建类之后

    因为:  代码一执行, 就创建一个类,由MyType创建Foo类,就执行Mytype的__init__方法了

    3、第三步

    class Foo(Base):         # 基类由MyType创建,Bar也由MyType创建
        a = 'aaa'
    
        def func(self, x):
            return x + 1

    现在有3个类, 运行脚本,会打印2遍("创建类之前","创建类之后")

    元类__new__/__init__/__call__的执行顺序

    class MyType(type):
        def __init__(self, *args, **kwargs):
            print("MyType: __init__")
            super(MyType, self).__init__(*args, **kwargs)
    
        def __call__(self, *args, **kwargs):
            print('MyType: __call__')
            super(MyType, self).__call__(*args, **kwargs)
    
    
    def with_metaclass(arg):
        return MyType('Base', (arg,), {})
    
    
    class Foo(with_metaclass(object)):
        a = 'aaa'
    
        def __init__(self, *args, **kwargs):
            print('Foo: __init__')
            super(Foo, self).__init__(*args, **kwargs)
    
        def __new__(cls, *args, **kwargs):
            print('Foo: __new__')
            return super(Foo, cls).__new__(cls)
    
        def func(self, x):
            return x + 1
    
    
    b = Foo()
    
    # MyType: __init__      这个是创建Base类的时候执行MyType的__init__
    # MyType: __init__      创建Foo类的时候,执行MyType的__init__
    # MyType: __call__      实例化 Foo(), 先执行MyType的__call__, 再执行Foo的__new__和__init__
    # Foo: __new__          然后才会执行Foo的__new__方法
    # Foo: __init__      最后执行Foo的__init__方法
  • 相关阅读:
    Invalid character found in method name. HTTP method names must be tokens
    使用idea合并分支
    jenkins企业级实战
    Custom runner class Runner should have a public constructor with signature R
    java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.([Ljava
    eclipse启动A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order
    windows配置jdk环境变量
    无法上传空目录到git仓库
    VirtualBox配置Centos网络和域名解析
    052(二十)
  • 原文地址:https://www.cnblogs.com/jin-yuana/p/10025553.html
Copyright © 2011-2022 走看看