python基础35 元类、mixins机制
Mixins机制
1.主类:就是大部分都是主要功能
2.辅类:就是一些辅助功能
3.辅类的类名也有讲究:一般以mixin、able、ible等结尾
4.继承的位置也有讲究,一般辅类在左边
class Vehicle: # 交通工具 def fly(self): ''' 飞行功能相应的代码 ''' print("I am flying") class CivilAircraft(Vehicle): # 民航飞机 pass class Helicopter(Vehicle): # 直升飞机 pass class Car(Vehicle): # 汽车并不会飞,但按照上述继承关系,汽车也能飞了 pass
Mixins机制后的代码
class Vehicle: # 交通工具 pass class FlyableMixin: def fly(self): ''' 飞行功能相应的代码 ''' print("I am flying") class CivilAircraft(FlyableMixin, Vehicle): # 民航飞机 pass class Helicopter(FlyableMixin, Vehicle): # 直升飞机 pass class Car(Vehicle): # 汽车 pass
元类简介
1.什么是元类?
产生类的类
type其实查看对象有那个类产生的
class MyClass(object): pass obj = MyClass() print(type(obj))# 查看obj是那个类产生的
你说我打印上述的type(MyClass) 它的结果应该是什么呢?
结果就是<class 'type'> ,那么就可以认为MyClass类就是有type类产生的
得出结论:我们之前使用class造出来的类都是有type类造出来的,就默认为type类是元类
产生类的两种方式
1.方式一:
class 类名():
pass
2.方式二:
既然所有的类都是有type类产生的,那么我们也可以用type来产生类
type(object_or_name, bases, dict)
type("类名", "父类", "类的名称空间")
3.为什么要学习元类?
元类是造出类的类,所以,我们可以对类进行高度的定制化
举个例子:
我让你写出来的类名必须是首字母大写?
思考:我们的定制化代码在哪里写呢?
类是如何产生的?类是有元类产生的type类,如果想改类的行为,应该在元类里的__init__方法中改.
对象是如何产生的? 是执行了产生这个对象的类内部的__init__方法
推导:已知推出来的未知
想改父类的__init__方法, 但是又不能修改源代码,所以我们可以写出来一个子类来继承父类type,在子类里面写代码,然后在从新执行一些父类的__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__方法,并且,__call__方法里面返回什么,那么,对象加括号的位置就是什么
推导:类名()会怎么样?
类名(),应该是会执行产生类的类中的__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') # 都是位置传参,强制要求必须是关键字传参
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY