Mixins机制、元类简介、产生类的两种方式、元类的进阶操作

发布时间 2023-07-02 17:43:42作者: Maverick-Lucky

Mixins机制

Mixins机制:子类混合不同类的功能,本质仍是多继承,不依赖于子类的实现。

使用:

  1. 主类:就是大部分都是主要的功能

  2. 辅类:就是一些辅助的功能

  3. 辅类的类名也有讲究:一般以mixin、able、ible等结尾

  4. 继承的位置也有讲究

eg:

class Vehicle:  # 交通工具    
    pass
class FlyMinix():    
    def fly(self):      
      '''飞行功能相应的代码'''        
        print("I am flying")
class CivilAircraft(FlyMinix, Vehicle):  # 民航飞机
    pass

class Helicopter(FlyMinix, Vehicle):  # 直升飞机
    pass

class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
    pass

import socketserver    

元类

元类:即产生类的类

‘type其实查看的是对象是由哪个类的产生的’

class MyClass(object):
    pass
obj = MyClass()
# <class '__main__.MyClass'>
# print(type(obj)) # 可以查看出obj对象是有哪个类产生的

"""你说我打印type(MyClass) 它的结果应该是什么呢?"""
class type(object):
    print(type(MyClass))  # <class 'type'>  我就可以认为MyClass类就是有type类产生的

我们之前用class造出来的类都是type类造出来的。默认情况下,所有的类的元类就是type

class Student():   
    pass
    print(type(Student)) # <class 'type'>
class C1():    
    pass
    print(type(C1))  # <class 'type'>

产生类的两种方式

1. class 类名():

  pass

2. 由于所有的类都是type类造出来的,所以我们也可以使用type类造出来一个新类,

type(object_or_name,basea,dict)
# 以上三个条件就是造出一个新类
type("类名","父类",“类的名称空间”)

为什么要学习元类?

  元类是造出类的类,所以可以对类进行高度的定制化。

定制化代码:如果想要该类的行为,应该在元类的__init__方法中做修改。

想要改变父类的__init__方法,但是不能直接修改源代码。可以写一个新的子类来继承父类type,然后再子类中写代码,在重新执行一些父类的__init__方法。

对象是如何产生的:执行了产生这个对象的类内部的__init__方法

 """元类不能直接继承"""
class MyTypeClass(type):
    def __init__(self, cls_name, cls_bases=None, cls_dict=None):
        print(cls_name, cls_bases, cls_dict)  # C1 () {'__module__': '__main__', '__qualname__': 'C1'}
        # cls_name:它就是类名
        # 限制类名必须是首字母大写
        if not cls_name.istitle():
            raise Exception("类名必须是首字母大写")
        super().__init__(cls_name, cls_bases=None, cls_dict=None)
               
class C1(metaclass=MyTypeClass):
    school = 'Sh'

class a(metaclass=MyTypeClass):
    pass

元类的进阶操作

类名(),会执行产生类的类中的__call__方法。而这个类恰好是元类type。

class MyClass(type):
    def __call__(self, *args, **kwargs):
        print("__call__ 执行了")
        print(args, kwargs)
        """限制传参的方式必须是关键字传参,只需要args是空就行"""
        if args:
            raise Exception("传参必须是关键字传参")
        super(MyClass, self).__call__(*args, **kwargs)
class C1(metaclass=MyClass):
    def __init__(self, name):
        print("__init__ 执行了")
        # self.name = name
"""看C1类里面的__init__方法和元类里面的__call__方法的执行顺序"""
# 得出结论,其实在执行类的__init__之前,先执行了__call__方法

obj = C1(name='kevin')  # 都是位置传参,强制要求必须是关键字传参