zoukankan      html  css  js  c++  java
  • Python 面向对象高阶-----metaclass

    Python 面向对象高阶-----metaclass  

     前言

     类也是对象,既然类是对象,那就自然是某个东西的实例化,这个东西就是type

    首先看下type是怎么回事

    type

    type最常用的方法就是查看类型,这只是他的基础用法罢了

    >>> print(type(1))
    <type 'int'>
    >>> print(type("1"))
    <type 'str'>
    >>> print(type(ObjectCreator))
    <type 'type'>
    >>> print(type(ObjectCreator()))
    <class '__main__.ObjectCreator'>

     type 通过传入其他参数也可以实现类的创建

    普通方式创建类:

    class Foo(object):
        bar = True
    
        def echo_bar(self):
            print(self.bar)

    继承关系的方式

    class FooChild(Foo):
        pass

    type 方式创建类:

    def echo_bar(self):
        print(self.bar)
    
    Foo = type('Foo', (), {'bar':True, 'echo_bar': echo_bar})

     有继承关系方式

    FooChild = type('FooChild', (Foo, ), {})

    以上两种方法是等效的

    type 的类创建方式的参数需要三个:

    • 类的名字
    • 一组"类的父类"的元组(tuple) (这个会实现继承,也可以为空)
    • 字典 (类的属性名与值,key-value的形式,不传相当于为空,如一般写法中的pass).

    metaclass

    说白了,函数 type 就是一个特殊的metaclass.
    python在背后使用 type 创造了所有的类。type是所有类的metaclass.

     在python中,一切皆为对象:整数、字符串、函数、类.所有这些对象,都是通过类来创造的.

        >>> age = 35
        >>> age.__class__
        <type 'int'>
    
        >>> name = 'bob'
        >>> name.__class__
        <type 'str'>
    
        >>> def foo(): pass
        >>> foo.__class__
        <type 'function'>
    
        >>> class Bar(object): pass
        >>> b = Bar()
        >>> b.__class__
        <class '__main__.Bar'>

    __class____class__则就是由 type 来的了

        >>> age.__class__.__class__
        <type 'type'>
        >>> name.__class__.__class__
        <type 'type'>
        >>> foo.__class__.__class__
        <type 'type'>
        >>> b.__class__.__class__
        <type 'type'>

    metaclass就是创造类对象的工具.如果你喜欢,你也可以称之为"类的工厂".

    type是python內置的metaclass。不过,你也可以编写自己的metaclass.

    指定 metaclass

    class Foo(metaclass=MyType):    # python 3 
      # __metaclass__ = MyType    # python 2 
      pass 

    流程

    Foo中有__metaclass__这个属性吗?

    有:

      如果有,会在内存中通过__metaclass__创建一个名字为Foo的类对象。

    没有:

      如果没有__metaclass__,它会继续在Bar(父类)中寻找,并尝试做和前面同样的操作。

      如果父类也没有找到__metaclass__,它就会在模块(module)中去寻找__metaclass__,并尝试做同样的操作。

      如果始终都找不到__metaclass__, 最终只能使用内置的type(这也是一个metaclass)来创建这个类对象。

    自定义metaclass

     使用metaclass的主要目的,是为了能够在创建类的时候,自动地修改类

     自定义 metaclass 首先就需要自定义一个不同于 type 的自定义 MyType,能够实现之前的 type 的类创建功能基础上在实现其他想要的功能

    class MyType(type):
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
    
        def __call__(cls, *args, **kwargs):
            obj = cls.__new__(cls)
    
            cls.__init__(obj,*args, **kwargs)
    
            return obj

    在创建类的时候指定 metaclass 为 自定义的 MyType 即可

    class Foo(object,metaclass=MyType):  # metaclass 指定由谁来创建这个类 
        a1 = 123
        def __init__(self):
            pass
    
        def __new__(cls, *args, **kwargs):
            return object.__new__(cls)
    
        def func(self):
            return 666

     那么在此类创建实例的时候的流程是怎样的呢?

    foo = Foo()

     流程

    创建类时

    先执行 MyType 的 __init__ 方法 ,由super 转向先执行 父类 type 的 __init__ 来创建类

    类实例化时

    当一个类在实例化时候,先执行 type 的 __call__ 方法 , __call__ 方法 的返回值就是实例化对象

    __call__ 内部调用:

      类.__new__ 方法 :创建对象

      类.__init__ 方法 :对象初始化

  • 相关阅读:
    Linux问题分析或解决_samba无法连接
    Android系统编译环境及连接工具配置
    Linux问题分析或解决_ssh无法连接
    新能力| 云开发静态网站托管能力正式上线
    如何在云开发静态托管中使用Hugo
    如何在云开发静态托管绑定静态域名
    3步搞定图像盲水印?试试云开发扩展能力
    不再忍受龟速 Github,你也可以试试在云开发上部署个人博客!
    云开发 For Web:一站式开发下一代 Serverless Web 应用
    下笔如有神的程序员来教你写作啦!
  • 原文地址:https://www.cnblogs.com/shijieli/p/10369507.html
Copyright © 2011-2022 走看看