元类metaclass
类的类型是什么?
元类,int、list等都是由元类创建的,type是Python的内建元类,任何类都有所属的元类(type)
print(type(1))
print(type(int))
---运行结果---
<class 'int'>
<class 'type'>
元类能干什么?
元类的核心思想,就是捣鼓类这个对象、使你能对其有着最高程度的控制权
元类和类的关系
元类metaclass可以创建元类,元类创建类(包括object也是由type创建的),类创建对象
如何使用元类创建类?
--方法一:通过type函数创建
type(类名, 父类以元组表示(针对继承的情况,可以为空),包含的属性用字典表示(名称和值))
例子
def __init__(self,name):
self.name = name
Student = type('Student',(object,),{'__init__':__init__,})
aa = Student('chloee')
print(Student)
print(aa.name)
------
<class '__main__.Student'>
chloee
---方法二:继承type元类
class MyMetaclass(type):
def __new__(cls,name,bases,attrs):
"""
创建对象(这个对象是一个类)
name:字符串,类的名称
bases:元组(基础类1,基础类2……)
attrs:字典(__dict__属性)
"""
name = 'Person'
attrs['name'] = 'chloe'
attrs['age'] = 18
bases = (object,)
return type.__new__(cls,name,bases,attrs)
class MyClass(object, metaclass=MyMetaclass):
pass
if __name__ == '__main__':
print(MyClass.name)
---运行结果--
chloe
这两个创建的例子,好像都不是很能突出元类到底有什么用,感觉这...直接继承不就更好了吗?
应用例子(例子是在另一个博主那找的,稍微改动了一下)
- 定义一个“人”(Person)类,它有三个方法:吃饭、睡觉、打游戏
- 定义 Person 的三个子类“小张”(Zhang)、“小王”(Wang)、“小江”(Jiang)
- 定义“人”的子类“小周”(Zhou),使用元类, 要求他:
-
- 吃饭像小王一样快,能力*2
- 睡觉像小张一样香,能力*3
- 打游戏像小江一样熟练,能力*4
"""
作为人类自然有吃喝玩的能力
而三人只是在吃喝睡中有较强能力
"""
class Person:
def __init__(self):
self.ability = 1
def eat(self):
print("Eat: ", self.ability)
def sleep(self):
print("Sleep: ", self.ability)
def play_game(self):
print("play game: ", self.ability)
class Wang(Person):
def eat(self):
print("Eat: ", self.ability * 2)
class Zhang(Person):
def sleep(self):
print("Sleep: ", self.ability * 3)
class Jiang(Person):
def play_game(self):
print("play game: ", self.ability * 4)
小周使用元类获得最高的权限,他创建了元类,获得第一个继承的父类的吃方法,获得第二个继承的父类的睡觉方法,获得第三个继承父类的打游戏方法
class MyMetaclass(type):
def __new__(cls, *args, **kwargs):
print(args)
name, bases, attrs = args[:3]
person1, person2, person3 = bases
def eat(self):
person1.eat(self)
def sleep(self):
person2.sleep(self)
def play_game(self):
person3.play_game(self)
attrs['eat'] = eat
attrs['sleep'] = sleep
attrs['play_game'] = play_game
return type(name,bases,attrs)
class Zhou(Zhang,Jiang,Wang,metaclass=MyMetaclass):
pass
注意这里小周他第一个继承的父类是小张,而小张的吃饭技能只是普通人类的水平
这里我们可以再定义一个人,”小红“(Hong)她也想像(Zhou)想的那样能吃能睡能打好游戏,但她就只继承就行了,继承顺序与Zhou一样
class Hong(Zhang,Jiang,Wang):
pass
输出一下小红和小周继承结果
if __name__ == '__main__':
h = Hong()
z = Zhou()
print('-------')
h.eat()
z.eat()
print('-------')
h.sleep()
z.sleep()
print('-------')
h.play_game()
z.play_game()
---运行结果----
-------
Eat: 2
Eat: 1
-------
Sleep: 3
Sleep: 1
-------
play game: 4
play game: 1
小红达到了她的目标(菱形继承),而小周因为改了继承顺序没对应上想要的人的能力
- 如果是继承的话,无论是eat、sleep还是play game都会寻找继承类中的eat、sleep和play game方法,即会找到wang的吃饭方法,zhang的睡觉方法,以及jiang的play game方法,那么都是获得最强的能力
- 但如果是创建元类的话,就能获得最大的控制权,按照继承的顺序获得对应人的能力,如果继承第一位是Wang,那么按照创建元类对象的方法来看,就调用Wang的吃方法,即能力*2。如果继承第一位是Jiang,那么就调用Jiang的吃方法,即能力只是*1。这样能很好的控制,继承哪个类的哪个方法
我们接着再试一下,把三位强人的吃喝玩游戏能力都改为不同于普通人的能力,小红还能获得小王的吃能力、小张的睡能力和小江的玩游戏能力吗?
class Wang(Person):
def eat(self):
print("Eat: ", self.ability * 2)
def sleep(self):
print("Sleep: ", self.ability * 0.8)
def play_game(self):
print("play game: ", self.ability * 0.7)
class Zhang(Person):
def sleep(self):
print("Sleep: ", self.ability * 3)
def eat(self):
print("Eat: ", self.ability * 0.6)
def play_game(self):
print("play game: ", self.ability * 0.99)
class Jiang(Person):
def play_game(self):
print("play game: ", self.ability * 4)
def sleep(self):
print("Sleep: ", self.ability * 0.88)
def eat(self):
print("Eat: ", self.ability * 0.77)
class Hong(Wang,Zhang,Jiang):
pass
class Zhou(Wang,Zhang,Jiang,metaclass=MyMetaclass):
pass
if __name__ == '__main__':
h = Hong()
z = Zhou()
print('-------')
h.eat()
z.eat()
print('-------')
h.sleep()
z.sleep()
print('-------')
h.play_game()
z.play_game()
Person类和MyMetaclass类没有变更
那么输出的结果是,在继承顺序按照小王、小张、小江的情况下,小周能够如愿获得三人的能力
-------
Eat: 2
Eat: 2
-------
Sleep: 0.8
Sleep: 3
-------
play game: 0.7
play game: 4
但其实貌似也只是理解一下有元类这么一个概念,好像也不太需要用上它哈哈哈。
”元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类“