Python元类-认识和应用

   

元类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%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类“  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值