元类

mac2022-06-30  106

元类

什么是元类?

要知道什么是元类就必须要了解一个大前提:python中所有的都是对象

在知道这个前提下我们就可以知道类也是一个对象 Σ(⊙▽⊙"a

那么一个对象就会有一个类来负责创建它

我们就把创建 “类”(实际也是一个对象)的 “类” 叫做——元类

怎么找到元类呢?

我们可以使用 type 方法来打印对象的类型

那么我们是不是也可以用 type 来打印类的数据类型呢?

print(type(list)) # <class 'type'> print(type(str)) # <class 'type'> print(type(object)) # <class 'type'>

就连所有的类的基类都是object类都是由元类所创建的

发现所有的类都是由 type 创建的。

??type??这不是经常用的一个内置方法吗?

怎么又变成了创建类的类了???

虽然我们看不到它的源码,但是它很知趣的给了我们大概的解释:

它可以传递一个参数或者传递三个参数:

一个参数:对象的类型(来自百度翻译)三个参数:一个新对象(来自百度翻译)

原来它真的就是可以用来创建对象。孤陋寡闻,孤陋寡闻。

创建类的参数的含义

object_or_name :类名bases : 继承的父类(元祖的形式传递)dict :类的命名空间(所有的属性与方法)

使用type创建一个类

既然我们已经知道type怎么用了那么我们就用这个 “马良笔” 来手动的创建一个类

def set_name(self,name): self.name = name def get_name(self): return self.name # 手动创建一个类 Custom = type('Custom',(object,),{'set_name': set_name, 'get_name': get_name}) # 实例化Custom类 obj = Custom() obj.set_name('gredae') print(obj.get_name()) # gredae

个人感觉class会不会也是重写了__enter__和__exit__方法来实现一个类的信息获取,再使用exce函数将类的名称空间里的所有属性与方法给写成一个字典,这样类的名称,类继承的所有父类,与类的属性与方法就全部都有了,再在底层调用type来生成类。。

自定义一个元类

type 好像是用C语言写的。嗯~算了,从入门到入坟。。。

我们换一种思路吧!我们直接继承 type 然后对 type 的方法重写来实现自定义一个元类,嗯~可行性很高。

class Mytype(type): pass Custom = type('Custom',(object,),{'set_name': set_name, 'get_name': get_name}) print(type(Custom)) # <class '__main__.Mytype'>

好了,我们实现了自定义元类,好像还没有重写它的方法。。

重写方法之前要知道实例化一个类经过了那些步骤

前面我们说到类也是对象,是由 type 创建的,那么我们将类实例化的时候是这样的 list() 当我们这样实例化类的时候就会调用 type 的 __call__ 方法而后在 __call__ 方法里面先使用 __new__ 创建一个空白的对象,什么都没有的对象。然后使用新创建的这个对象来调用该类的 __init__ 来初始化这个对象最后再返回该对象。这样才能实例化一个类。

虽然上面的步骤很多,但是实际实现起来也很多。嗯,没错。

我们来实现自定义元类:

class Mytype(type): def __call__(self, *args, **kwargs): obj = object.__new__(self) obj.__init__(*args, **kwargs) return obj class Custom(metaclass=Mytype): def set_name(self, name): self.name = name def get_name(self): return self.name f = Custom() print(type(f)) # <class '__main__.Custom'> print(type(Custom)) # <class '__main__.Mytype'> f.set_name('gredae') print(f.get_name()) # gredae

终于一个功能齐全的自定义元类完成了。。

属性查找

最后再来说下类的属性查找和对象的属性查找

类:先从类本身中找 -> mro继承关系去父类中找 -> 去自己定义的元类中找 -> type中 -> 报错对象:先从对象自身找 -> 类中找 -> mro继承关系去父类中找 -> 报错

转载于:https://www.cnblogs.com/Gredae/p/11454220.html

最新回复(0)