zoukankan      html  css  js  c++  java
  • metaclass of python

    Metaclasses

    https://www.python.org/dev/peps/pep-3115/

    元类的诞生是来自于大量有趣的用例, 要求在类创建的过程中,就可以参与到类的定制逻辑中去。

    The primary reason for changing the way metaclasses work, is that there are a number of interesting use cases that require the metaclass to get involved earlier in the class construction process than is currently possible. Currently, the metaclass mechanism is essentially a post-processing step. With the advent of class decorators, much of these post-processing chores can be taken over by the decorator mechanism.

    https://en.wikipedia.org/wiki/Metaclass#:~:text=In%20object-oriented%20programming%2C%20a%20%EE%80%80metaclass%EE%80%81%20is%20a%20%EE%80%80class%EE%80%81,that%20do%2C%20the%20extent%20to%20which%20metaclasses%20

    元类也是一种类,这种类的示例 还是 类, 创建类的类。

    In object-oriented programming, a metaclass is a class whose instances are classes. Just as an ordinary class defines the behavior of certain objects, a metaclass defines the behavior of certain classes and their instances. Not all object-oriented programming languages support metaclasses. Among those that do, the extent to which metaclasses can override any given aspect of class behavior varies.

    metaclass vs class

    https://realpython.com/python-metaclasses/#custom-metaclasses

    根据class生成instance

    >>> class Foo:
    ...     def __init__(self):
    ...         self.attr = 100
    ...
    
    >>> x = Foo()
    >>> x.attr
    100
    
    >>> y = Foo()
    >>> y.attr
    100
    
    >>> z = Foo()
    >>> z.attr
    100

    根据metaclas生成class

    >>> class Meta(type):
    ...     def __init__(
    ...         cls, name, bases, dct
    ...     ):
    ...         cls.attr = 100
    ...
    >>> class X(metaclass=Meta):
    ...     pass
    ...
    >>> X.attr
    100
    
    >>> class Y(metaclass=Meta):
    ...     pass
    ...
    >>> Y.attr
    100
    
    >>> class Z(metaclass=Meta):
    ...     pass
    ...
    >>> Z.attr
    100

    Metaclass Usecases

    https://www.geeksforgeeks.org/python-metaclasses/

    Class Verification

    类定义需要满足一定条件。

    class MainClass(type):
        def __new__(cls, name, bases, attrs):
            if 'foo' in attrs and 'bar' in attrs:
                raise TypeError('Class % s cannot contain both foo and bar 
    attributes.' % name)
            if 'foo' not in attrs and 'bar' not in attrs:
                raise TypeError('Class % s must provide either a foo 
    attribute or a bar attribute.' % name)
            else:
            print('Success')
                
    
            return super(MainClass, cls).__new__(cls, name, bases, attrs)
    
    class SubClass(metaclass = MainClass):
        foo = 42
        bar = 34
    
    
    subCls = SubClass()

    Prevent  inheriting the attributes

    定义类的行为,

    如果类是抽象类, 则不需要校验必备函数是否存在

    如果类是可实例化类, 则需要校验必备函数是否存在

    A metaclass is an efficient tool to prevent sub class from inheriting certain class functions. This scenario can be best explained in the case of Abstract classes. While creating abstract classes, it is not required to run the functionality of the class. Let’s have a look at the below code. 

    class MetaCls(type):
        def __new__(cls, name, bases, attrs):
            # If abstract class, then skip the metaclass function
            if attrs.pop('abstract', False):
                print('Abstract Class:', name)
                return super(MetaCls, cls).__new__(cls, name, bases, attrs)
            
            # metaclass functionality
            if 'foo' in attrs and 'bar' in attrs:
                raise TypeError('Class % s cannot contain both foo and bar 
    attributes.' % name)
            if 'foo' not in attrs and 'bar' not in attrs:
                raise TypeError('Class % s must provide either a foo 
    attribute or a bar attribute.' % name)
            print('Normal Class:', name)
            return super(MetaCls, cls).__new__(cls, name, bases, attrs)
    
    class AbsCls(metaclass = MetaCls):
        abstract = True
        
    
    class NormCls(metaclass = MetaCls):
        foo = 42

    Dynamic generation of classes

    使用type元类, 来实现类的动态创建。

    class FoodType(object):
        events = []
    
        def __init__(self, ftype, items):
            self.ftype = ftype
            self.items = items
            FoodType.events.append(self)
    
        def run(self):
            print("Food Type: % s" %(self.ftype))
            print("Food Menu:", self.items)
    
        @staticmethod
        def run_events():
            for e in FoodType.events:
                e.run()
    
    def sub_food(ftype):
        class_name = ftype.capitalize()
        def __init__(self, items):
            FoodType.__init__(self, ftype, items)
        # dynamic class creation and defining it as a global attribute    
        globals()[class_name] = 
        type(class_name, (FoodType, ), dict(__init__ = __init__))
                
            
    if __name__ == "__main__":
        foodType = ["Vegetarian", "Nonvegetarian"]
        foodItems = "Vegetarian(['Spinach', 'Bitter Guard']);
    Nonvegetarian(['Meat', 'Fish'])"
        # invoking method for dynamic class creation.
        [sub_food(ftype) for ftype in foodType]
        # executing dynamic classes.
        exec(foodItems)
        FoodType.run_events()

    类的创建过程

    https://lotabout.me/2018/Understanding-Python-MetaClass/

    要了解元类(meta-class)的作用,我们就需要了解 Python 里类的创建过程 ,如下:

    1. 当 Python 见到 class 关键字时,会首先解析 class ... 中的内容。例如解析基类信息,最重要的是找到对应的元类信息(默认是 type)。
    2. 元类找到后,Python 需要准备 namespace (也可以认为是上节中 typedict 参数)。如果元类实现了 __prepare__ 函数,则会调用它来得到默认的 namespace 。
    3. 之后是调用 exec 来执行类的 body,包括属性和方法的定义,最后这些定义会被保存进 namespace。
    4. 上述步骤结束后,就得到了创建类需要的所有信息,这时 Python 会调用元类的构造函数来真正创建类。

    如果你想在类的创建过程中做一些定制(customization)的话,创建过程中任何用到了元类的地方,我们都能通过覆盖元类的默认方法来实现定制。这也是元类“无所不能”的所在,它深深地嵌入了类的创建过程。

    Meta Class in Models – Django

    https://www.geeksforgeeks.org/meta-class-in-models-django/#:~:text=Check%20More%20About%20Django%20models%20here%20%E2%80%93%20Django,changing%20order%20options%2Cverbose_name%20and%20lot%20of%20other%20options.

    元类在Django model的定义中也有出现, 用于定义模型的一些属性。

    但是其不符合元类使用语法,

    经过查询其代码,发现, 其仅仅是一个模型类中的一个属性。

    例如存储 abstract属性。

    这里Meta应该是原型的意思, 存储模型的一些抽象属性。

            attr_meta = attrs.pop('Meta', None)
    
    。。。
            abstract = getattr(attr_meta, 'abstract', False)

    What is Model Meta?

    Model Meta is basically the inner class of your model class.

    Model Meta is basically used to change the behavior of your model fields like changing order options,verbose_name and lot of other options. It’s completely optional to add Meta class in your model.

    To use model meta you have to add class Meta in your model like this

    class student(models.Model):
        class Meta:
            options........
    class student(models.Model):
      class Meta:
          abstract = True
    出处:http://www.cnblogs.com/lightsong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    微博Feed流
    朋友圈
    Go命令行—compile
    Practical Go: Real world advice for writing maintainable Go programs
    Nginx Cache-Control
    Redis 主从复制
    JAVA
    Tomcat
    Tomcat
    CentOS 7
  • 原文地址:https://www.cnblogs.com/lightsong/p/15391478.html
Copyright © 2011-2022 走看看