python中MetaClass的一些用法

元类在许多编程语言中都有这样的概念,我们都知道类可以创建对象,类本身也是对象,既然它是对象,那么它也必须被创建,元类是专门用来创建类对象的,所以,这为我们提供了操纵或监听类的能力。

[En]

Metaclass has such a concept in many programming languages, we all know that the class can create objects, the class itself is also an object, since it is an object, then it must also be created, metaclass is specifically used to create class objects, so, this provides us with the ability to manipulate or listen to classes.

通常我们用这种方式创建一个类:

[En]

Usually we create a class in this way:

class MyClass(object):
    def method(self):
        return 1

instance1 = MyClass()
print(instance1.method())

如果您将类视为对象并使用元类,我们将创建一个如下所示的类:

[En]

If you think of a class as an object and use a metaclass, we create a class like this:

def method(self):
    return 1

klass = type('MyClass', (object,), {'method': method})
instance1 = klass()
print(instance1.method())

如果你看一下你写的方式,它没有太大的不同。MetaClass真正有用的地方在于我们可以定制元类。让我们来看一段代码:

[En]

If you look at the way you write it, it doesn’t make much difference. What’s really useful about MetaClass is that we can customize metaclasses. Let’s take a look at a piece of code:

class RevealingMeta(type):
    def __new__(mcs, name, bases, namespace, **kwargs):
        print(mcs, "__new__ called")
        return super().__new__(mcs, name, bases, namespace)

    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        print(metacls, "__prepare__ called")
        return super().__prepare__(name, bases, **kwargs)

    def __init__(cls, name, bases, namespace, **kwargs):
        print(cls, "__init__ called")
        super().__init__(name, bases, namespace)

    def __call__(cls, *args, **kwargs):
        print(cls, "__call__ called")
        return super().__call__(*args, **kwargs)

上面的代码可以看作是固定的编写方式,更重要的概念是调用这四个方法的时间:

[En]

The above code can be regarded as a fixed way of writing, and the more important concept is the timing of calling these four methods:

  • __new__ 当某个类被创建的时候会调用
  • __prepare__ 在创建类的时候,可以传入额外的字典 class Klass(metaclass=Metaclass, extra="value"):,这个方法就是用来创建接收dict的,所以这个方法会在 __new__前边调用
  • __init__ 这个方法算是对 __new__的一些补充
  • __call__ 这个方法会在类被创建的时候调用

让我们使用由上述代码创建的元类来创建一个类:

[En]

Let’s use the metaclass created by the above code to create a class:

class RevealingMeta(type):
    def __new__(mcs, name, bases, namespace, **kwargs):
        print(mcs, "__new__ called")
        return super().__new__(mcs, name, bases, namespace)

    @classmethod
    def __prepare__(metacls, name, bases, **kwargs):
        print(metacls, "__prepare__ called")
        return super().__prepare__(name, bases, **kwargs)

    def __init__(cls, name, bases, namespace, **kwargs):
        print(cls, "__init__ called")
        super().__init__(name, bases, namespace)

    def __call__(cls, *args, **kwargs):
        print(cls, "__call__ called")
        return super().__call__(*args, **kwargs)

class RevealingClass(metaclass=RevealingMeta):
    def __new__(cls, *args, **kwargs):
        print(cls, "__new__ called")
        return super().__new__(cls)

    def __init__(self):
        print(self, "__init__ called")
        super().__init__()

如果此时直接执行代码,它将打印出来:

[En]

If the code is executed directly at this time, it will print out:

 __prepare__ called
 __new__ called
 __init__ called
 __call__ called

这意味着类一创建,上述方法就会被调用,而这些方法的调用与实例的创建无关。

[En]

This means that the above methods will be called as soon as the class is created, and the invocation of these methods has nothing to do with the creation of the instance.

instance12 = RevealingClass()

在上述打印后,它将打印出来:

[En]

After the above print, it will print out:

 __new__ called
 __init__ called

这是元类的基本用法。它通常在很多框架中使用,但也容易出错。我们可以随意为类指定元类,如果元类不实现这些方法,它可能会崩溃。

[En]

This is the basic use of metaclass. * it is generally used in a lot of framework, but it is also error-prone. We can specify a metaclass for a class at will, and if the metaclass does not implement these methods, it may crash. *

Original: https://www.cnblogs.com/machao/p/8708584.html
Author: 马在路上
Title: python中MetaClass的一些用法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/6662/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部