东源建设局网站,自豪地采用 wordpress.,苏州万户网络,天津各区房价一览表1. 元类是什么
众所周知#xff0c;对象由类实例化而来#xff0c;类是对象的模板#xff0c;而python一切皆对象#xff0c;类也是对象#xff0c;它由元类#xff08;type#xff09;创建#xff0c;所以元类是类的类#xff0c;是类的模板
2. 创建类的另一种方法…1. 元类是什么
众所周知对象由类实例化而来类是对象的模板而python一切皆对象类也是对象它由元类type创建所以元类是类的类是类的模板
2. 创建类的另一种方法
一般情况下我们使用class关键字申明一个类就像
class Demo:def __init__(self,name,age):self.name nameself.age agedef output(self):print(name is str(self.name) age is str(self.age))if __name__ __main__:demo Demo(Bob,18)demo.output()python 中所有的类都是通过type创建的所以当我们使用type()函数查看类的类型时会显式class type class Demo:pass type(Demo)
class typedemo Demo()type(demo)
class __main__.Demo通过类实例化出来的对象的类型是class 类名这样也更加验证了所有类都是由元类type实例化而来 通过type创建类
可以看一下type的文档type可以传入三个参数object_or_name, bases, dict,当只有一个参数是object时返回该对象的类型就是最常使用的这种情况当传入name, bases, dict参数时会返回一个类name是类名bases是基类元组dict是类中属性和方法的字典
class type(object):type(object_or_name, bases, dict)type(object) - the objects typetype(name, bases, dict) - a new type我们使用type重写一下上面的Demo类
# 模拟__init__()
def __init__(self,name,age):self.name nameself.age agedef output(self):print(name is str(self.name) age is str(self.age))class_name Demo
class_bases (object,)
class_dict {__init__:__init__,output: output,
}# type(name, bases, dict) - a new type
Demo type(class_name,class_bases,class_dict)
demo Demo(Bob,18)
demo.output() # name is Bob age is 18实际上每次用class定义类时执行的都是type()方法
3. MetaClass
既然所有类都是由type创建的那我们就可以控制类的创建行为这就需要使用元类metaclass
元类用来创建类实质上也是一个类继承自type__new__是真正的构造函数用来分配内存空间__new__(cls: type, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) - type
def add(self, value):print(add one value)self.append(value)class ListMetaclass(type):def __new__(mcs, name, bases, namespace):namespace[add] addreturn type.__new__(mcs, name, bases, namespace)class MyList(list, metaclassListMetaclass):passli MyList()
li.add(1)
print(li)在用class定义类时括号中可以指定metaclass指定后会创建__metaclass__,python在创建类的时候会先检查有没有__metaclass__,如果有就会以此方法创建对象没有就会逐级向上查找父类中有没有该如果找到当前package中还没有找到就会使用默认的type创建(调用metaclass.__new__()) 值得注意的是如果我们在做类的定义时在class声明处传入关键字metaclassListMetaclass那么如果传入的这个metaclass有__call__函数这个__call__函数将会覆盖掉MyList class的__new__函数。这是为什么呢请大家回想一下当我们实例化MyList的时候用的语句是L1MyList()而我们知道__call__函数的作用是能让类实例化后的对象能够像函数一样被调用。也就是说MyList是ListMetaclass实例化后的对象而MyList()调用的就是ListMetaclass的__call__函数。另外值得一提的是如果class声明处我们是让MyList继承ListMetaclass那么ListMetaclass的__call__函数将不会覆盖掉MyList的__new__函数。 元类在一般情景下很少用到但在像ORM中还是会有应用的ORM对象关系映射ORM看这位大佬的文章谈谈Python中元类Metaclass(二)ORM实践
4. 总结
通过class定义的类其实是通过type()创建的type(object_or_name, bases, dict)如果想要控制类的创建行为需要在创建类时指定metaclass,一旦指定了metaclass就会在class上添加__metaclass__创建类时会找__metaclass__指向的类并用这个类创建类如果找不到就会调用默认的type()
参考文章
Python中的元类(metaclass) 谈谈Python中元类Metaclass(一)什么是元类 Python之元类