理解Python中的元类
1.引入
Python中一切皆对象,所谓对象就是由类创建出来,那么创建对象的类本身也是一个对象,也就是说创建对象的类本身也由别的什么类创建,这种创建类的类就叫元类
.
2.元类是谁?
type
函数就是元类,没错就是那个打印数据类型的函数,也就是说是type
创建了类.
我们写一个类然后打印一下他的属性看看
In [4]: class MyClass(object):
...: pass
...:
In [5]: type(MyClass)
Out[5]: type
可以看到MyClass
类的类型是type
,用Python语言来描述这种关系就是:
MyClass = type()
3.type
和object
的区别
刚接触元类时很容易搞混这两者.区别如下
type
是说有类的创建者
object
是所有类的父类
怎么理解呢?记住以下几点就OK了(可能有点绕)
type
和object
不是同一层的东西type
是元类object
是普通类- 元类的对象是普通类,普通类的对象就是普通对象
- 继承自
object
的类包括object
本身都是普通类 - 继承自
type
的类都是元类 - 普通类都是元类的对象
In [9]: type(object)
Out[9]: type
那么是谁创建了type
呢?这个问题留给你们自己去找答案,我相信有很多小伙伴已经猜到了.
3.通过type
创建普通类
由type
创建普通类的格式为
变量名 = type("类名", ("继承的类",), {"属性名":"属性值"})
第二个参数是元组类型
举个例子
In [11]: Myclass = type("ClassName", (object,), {"name": "kainhuck", "foo":"bar"})
In [12]: Myclass
Out[12]: __main__.ClassName
可以看到Myclass不是真正的类名,真正的类名是ClassName
.
创建一个名为ClassA
,继承自object
类,并带有属性name
和方法printName
的类,写法如下
In [15]: def printName(self):
...: print(self.name)
...:
In [16]: ClassA = type("ClassA",(object,),{"name":"myName", "printName":printName})
In [17]: a = ClassA()
In [18]: a.printName()
myName
4.创建自己的元类
前面已经有过提示,我们可以通过继承type
来创建自己的元类
举个例子:
In [20]: class MetaClass(type):
...: pass
...:
In [21]: ClassA = MetaClass("ClassA",(object,),{"name":"myName", "printName":printName})
In [22]: a = ClassA()
In [23]: a.printName()
myName
这个例子中我只继承type
没有增加任何新的功能
我们知道创建一个对象的功能由__new__
函数实现,下面我们通过修改__new__
函数来创建一个必须含有printName
方法的类.
In [30]: class MyMetaClass(type):
...: def __new__(cls, name, bases, attrs):
...: func = attrs.get("printName", None)
...: if not callable(func):
...: raise NotImplementedError("必须创建一个名为 printName 的函数")
...: return type.__new__(cls, name, bases, attrs)
...:
...:
In [31]: ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":"not callable"})
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-31-772aa102a27f> in <module>
----> 1 ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":"not callable"})
<ipython-input-30-c2ffcc442a77> in __new__(cls, name, bases, attrs)
3 func = attrs.get("printName", None)
4 if not callable(func):
----> 5 raise NotImplementedError("必须创建一个名为 printName 的函数")
6 return type.__new__(cls, name, bases, attrs)
7
NotImplementedError: 必须创建一个名为 printName 的函数
In [32]: ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":printName})
In [33]:
可以看到如果我们定义的类没有创建printName
函数就会报错.
5.类工厂
所谓类工厂就是生产类的地方,我们可以设计一个函数,使该函数可以通过参数来返回不同的类.
男人和女人都是人,但是不同性别的人剪头发的时间不一样.我们就可以定义一个类工厂来按需求产生不同的类.
def Person(sex):
def manCut(self):
print("我是男人,我剪头发很快")
def womanCut(self):
print("我是女人,我剪头发很慢")
if sex == "man":
return type("man", (object,), {"hairCut": manCut})
elif sex == "woman":
return type("woman", (object,), {"hairCut": womanCut})
else:
print("Error")
Man = Person("man")
Woman = Person("woman")
lilei = Man()
hanmeimei = Woman()
out:
我是男人,我剪头发很快
我是女人,我剪头发很慢