zoukankan      html  css  js  c++  java
  • python黑魔法之metaclass

    最近了解了一下python的metaclass,在学习的过程中,把自己对metaclass的理解写出来和大家分享。

    首先, metaclass 中文叫元类,这个元类怎么来理解呢。我们知道,在Python中,一切都是对象。我们定义一个类,然后实例化,得到了一个类的实例对象。我们可以把类理解成创建实例对象的模板。其实,这个模板,也就是类本身,也是一个对象。既然类也是对象,那么我们就可以对他进行很多操作。比如,把类作为函数的参数,创建类的引用等等。那么创建类的模板,就是元类。

    在Python中,我们很早就接触了一个函数 type,用来返回对象的类型。比如

    In [1]: print(type(1))
    <type 'int'>
    In [2]: print(type("1"))
    <type 'str'>
    In [3]: def foo():pass
    In [4]: print (type(foo))
    <type 'function'>
    In [5]: class Foo():pass
    In [6]: print(type(Foo()))
    <type 'instance'>
    In [7]: print(type(Foo))
    <type 'classobj'>

    其实 type函数还有另外一个用处,那就是用来创建类,用法就是

    type(classname,(superclassname,),{attrs}),我们来看一下:

    MyClass = type("MyClass",(),{})

    其实等效于

    class MyClass():
        pass

    我们说过,metaclass是创建类的类,所以,type就是一个metaclass。我们来验证一下

    In [23]: age.__class__
    Out[23]: int
    In [24]: name.__class__
    Out[24]: str
    In [25]: MyClass().__class__
    Out[25]: __main__.MyClass
    In [26]: MyClass().__class__.__class__
    Out[26]: type
    In [29]: age.__class__.__class__
    Out[29]: type
    In [30]: name.__class__.__class__
    Out[30]: type

    type是内置的metaclass,我们也可以自己定义自己的元类。在定义类的时候,定义 __metaclass__属性,这种情况下,Python就会使用metaclass 来创建类。具体模式如下:

    在创建类时,Python会寻找有没有定义__metaclass__,如果有,就用定义好的metaclass来创建类。

    如果在当前类找不到 __metaclass__,Python会在当前模块下寻找__metaclass__

    如果还是找不到,Python会寻找当前类第一个父类的__metaclass__,直到最后的内建函数type()

    那么__metaclass__定义到底是什么呢?

    是任何能够创建类的,比如type或者type的子类

    所以metaclass的目的在类创建的时候自动的修改类,举个例子,我们想把一个类里所有的属性前面都加一个my_前缀,使用metaclass的方式就比较简单

    class MyAttrMetaclass(type):
        def __new__(cls, clsname, bases,dct):
            my_attr = {}
            for name, val in dct.items():
                if not name.startswith('__'):
                    my_attr["my_"+name] = val
                else:
                    my_attr[name] = val
            return type.__new__(cls, clsname, bases, my_attr)
    
    
    class Foo():
        __metaclass__= MyAttrMetaclass
        test_age = 1
        test_name = "test"
    
    print(hasattr(Foo,"test_age"))
    False
    print(hasattr(Foo,"my_test_age"))
    True

    可以看到通过元类的方式,我们的类Foo的属性被修改了。

    最后一个问题就是我们在什么情况下会用到metaclass呢?

    常见的例子有Django ORM 的Model类,

    我们定义一个Person类集成Model

    class Person(Model):
      name = models.CharField(max_length=30)
      age = models.IntegerField()
    
    p = person(name="haha",age="31")

    p.age 返回的是int 而不是IntegerField(),这就是因为在Model中使用的metaclass动态修改类

    本文总结了黑魔法metaclass的定义,用法,主要参考了http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 

  • 相关阅读:
    lntelliJ IDEA 皮肤设置
    Maven安装与配置
    lntelliJ IDEA 使用 Maven 与 每次新建项目都需要重新配置的解决方案
    Spring Boot 扫描机制说明
    Spring Boot Filter 使用指南
    Gradle构建CAS4.2.7爬坑指南
    Java的垃圾回收
    final与static
    angular directive自定义指令
    ui-router
  • 原文地址:https://www.cnblogs.com/yuwhuawang/p/6701767.html
Copyright © 2011-2022 走看看