元类

Python 小记 2018-12-15 3268 字 2366 浏览 点赞

元类

什么是元类?
答:类的类。

如何理解?可以这样说,我们用类来创建一个实例对象如myObject = MyClass()。事实上Python中的类也是对象(万物皆对象),所以也需要通过类的类创建,如MyClass = MetaClass()。这个类的类(MetaClass)就是元类

元类从哪来

通常我们用type(object)来获取一个对象的类型,如:

>>> type(512)
<class 'int'>
>>> type("zhong")
<class 'str'>

然而type()还有另一个用处:type(name, bases, dict) -> a new type,也就是用来创建一个类。一般我们都是通过class关键字来定义一个类:

class  MyClass(object):
    pass

但也可以用type动态创建一个类:

>>> MyClass = type("MyClass", (), {})
>>> myObject = MyClass()

其实type就是一个元类。Python中所有类都是通过type来创建的。我们可以通过__class__来验证:

>>> str.__class__
<class 'type'>
>>> int.__class__
<class 'type'>
>>> object.__class__
<class 'type'>

我们自己用class定义出来的类也是如此:

>>> class MyClass(object):
    pass

>>> myObject = MyClass()
>>> myObject.__class__.__class__
<class 'type'>

type的用法

函数接口:type(name, bases, dict)

  • name:类名
  • bases:基类,接收一个元组
  • dict:绑定类的方法和属性

现在通过类比的方式来理解type()的使用。

第一种:利用class关键字定义类

class MyClass(object):
    def __init__(self):
        self.string = "this is a test class"

    def print_str(self):
        print(self.string)

if __name__ == "__main__":
    myObject = MyClass()
    print(myObject.string)
    myObject.print_str()

# 输出:
#this is a test class
#this is a test class

第二种:利用type创建类

string = "this is a test class"

def print_str(self):
    print(self.string)

MyClass = type(
               "MyClass",
               (object,),
               dict(string=string, print_str=print_str))

if __name__ == "__main__":
    myObject = MyClass()
    print(myObject.string)
    myObject.print_str()

# 输出:
#this is a test class
#this is a test class

创建类的过程

当我们用如下方法

class MyClass(object):
    pass

Python做了这样的操作:(1)在MyClass中寻找metaclass,如果存在,用它来创建名MyClass的类对象;(2)如果不存在,就去父类(这里是object)中找;(3)最后都没找到,利用Python内置的type()创建这个类对象

注: 在Python2中,如果没在父类中找到metaclass会去模块层次中寻找,但似乎Pythony3里取消了,这里留疑

metaclass的使用

比如,我们想给自己定义的类添加author属性,即所有实例化的对象都可以执行语句:a.author来获取作者信息,实现代码如下:

def upper_attr(name, bases, attrs):
    # 增加author信息
    attrs.update({"author":"Guan"})
    # 返回一个类的类
    return type(name, bases, attrs)

# metaclass的使用方法
class MyClass(object, metaclass=upper_attr):
    pass


if  __name__ == "__main__":
    myObj = MyClass()
    print(myObj.author)

# 输出:
#Guan

事实上,更建议metaclass对接一个自定义的元类,而不是函数

# 需要继承自type
class MyMetaClass(type):
    def __new__(cls, name, bases, attrs):
        attrs.update({"author":"Guan"})
        return super().__new__(cls, name, bases, attrs)


class MyClass(object, metaclass=MyMetaClass):
    pass


if  __name__ == "__main__":
    myObj = MyClass()
    print(myObj.author)

# 输出
#Guan

元类的作用

元类的主要目的是为了当创建类时能够自动地改变类。正如我前边的列子,创建的每一个类都能够自动添加author属性。

感谢

  • 参考 伯乐在线(深刻理解Python中的元类(metaclass))
  • 参考 廖雪峰(使用元类)
  • 参考 知乎专栏(一步步理解Python中的元类metaclass)


本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论