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 里类的创建过程 ,如下:
- 当 Python 见到
class
关键字时,会首先解析class ...
中的内容。例如解析基类信息,最重要的是找到对应的元类信息(默认是type
)。- 元类找到后,Python 需要准备 namespace (也可以认为是上节中
type
的dict
参数)。如果元类实现了__prepare__
函数,则会调用它来得到默认的 namespace 。- 之后是调用
exec
来执行类的 body,包括属性和方法的定义,最后这些定义会被保存进 namespace。- 上述步骤结束后,就得到了创建类需要的所有信息,这时 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
相关文章
- Python 四舍五入函数 round
- Python查看大佬Github上全部项目的Star数量和统计
- 《Head First Python》学习笔记03 异常处理
- python编程:json indent can't multiply sequence by non-int of type 'str'
- python 对xls写入信息 和 追加
- IndexError: invalid index of a 0-dim tensor. Use `tensor.item()` in Python
- 成功解决:Can‘t find Python executable “python“, you can set the PYTHON env variable.
- 第7.4节 Python中与众不同的类
- 已解决tensorflow.python.framework.errors_impl.InvalidArgumentError: slice index 1 of dimension 0 out of
- Python pandas.DataFrame.first函数方法的使用
- Python pandas.DataFrame.equals函数方法的使用
- python 发送邮件
- setTimeout and setInterval counterpart of Python
- asyncio of Python
- data persistence of Python
- enum of Python
- weakref of Python
- heapq of python
- parallel computing of Python
- python学习之美多商城(四):用户部分--注册业务接口分析、跨域CORS、使用celery异步完成发送短信、
- python学习之数据分析(二):Matplotlib库:常用画图技巧, 折线图, 散点图,柱状图,直方图, 饼图