x是类Foo的一个实例
Foo是type元类的一个实例
type也是type元类的一个实例,所以他是他自己的一个实例
动态定义类
type(参数) 返回参数的类型,通常与对象的__class__属性相同
你也可以传三个参数type(<name>,<bases>,<dct>)调用type()
<name>指定类名,成为__name__的属性
<bases>指定继承类的基类元组,成为__bases__的属性
<dct>指定包含类主体定义的名称空间字典,成为__dct__的属性
自定义元类
重新思考一下先前的这个例子:
表达式Foo()创建一个新的类Foo的实例。当解释器遇到Foo(),将按一下顺序进行解析:
调用Foo父类的__call__()方法。由于Foo是标准的新式类,它的父类是type元类,所以type的__call__()方法被调用。
__call__()方法按以下顺序进行调用:
__new__()
__init__()
如果Foo没有定义__new__()和__init__(),那么将调用Foo父类的默认方法。但是如果Foo定义这些方法,就会覆盖来自父类的方法,这就允许在实例化Foo时可以自定义行为。
这会修改类Foo的实例化行为:每次Foo创建实例时,默认情况下都会将名为attr的属性进行初始化,将该属性设置为100。(类似于这样的代码通常会出现在__init__()方法中,不会出现在__new__()方法里,这个例子仅为演示目的而设计。)
现在,正如前面重申的那样,类也是对象。假设你想类似地在创建类Foo时自定义实例化行为。如果你要遵循上面的模式,则需要再次定义一个自定义方法,并将其指定为类Foo的实例的__new__()方法。Foo是type元类的一个实例,所以代码如下所示:
阿偶,你可以看到,不能重新指定元类type的__new__()方法。Python不允许这样做。
可以这么讲,type是派生所有新式类的元类。无论如何,你真的不应该去修改它。但是,如果你想自定义一个类的实例化,那么有什么办法呢?
一种可能的解决方案是自定义元类。本质上,不是去试图修改type元类,而是定义自己派生于type的元类,然后对其进行修改。
第一步是定义派生自type的元类,如下:
https://mp.weixin.qq.com/s/HTNRNheuNTLo-Lvmqz46AQ