Mixins机制
class Vehicle: # 交通工具
pass
class FlyMinix:
"""
将主类中有多个子类要继承的方法单独拿出来,重新定义一个类,将这个有给有需要的子类继承,在主类中不再写这个方法
"""
def fly(self):
"""
跟飞行相关的功能
:return:
"""
print("I am flying")
class CivilAircraft(FlyMinix, Vehicle): # 民航飞机
pass
class Helicopter(FlyMinix, Vehicle): # 直升飞机
pass
class Car(Vehicle): # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
pass
"""
1. 主类:就是大部分都是主要的功能
2. 辅类:就是一些辅助的功能
3. 辅类的类名也有讲究:一般以mixin、able、ible等结尾
4. 继承的位置也有讲究:一般辅类在主类的左边,
"""
元类的介绍
在了解元类之前我们做一些推理
1、什么是对象呢?
'对象是不是就是调用了类产生了对象'
2、那么类又是怎么产生的呢?
'按照对象产生的逻辑,那么“我们创建的类”是不是就是通过调用另一个类所产生的新类'
3、既然我们知道了类是如何产生的以后,那么我们再说说什么是元类?
'元类就是产生了类的类就是元类,即“type”'
说到这里可能就奇怪了,type不是查看数据类型的吗
比如 : print(type(123)) # <class 'int'>
其实在没有学类之前,type的功能确实质数查看数据类型,但是当我们学完类以后就应该知道,type查看的其实是"""对象是有哪个类产生的!"""
Eg:
class Myclass:
pass
obj = Myclass()
print(type(obj)) # <class '__main__.Myclass'> 说明obj这个对象是由Myclass产生的
# 如果打印Myclass呢
print(type(Myclass)) # <class 'type'>
# 那我们是不是就可以理解为Myclass这个类是由type这个类产生的
"""得出结论:我们之前使用class造出来的类都是有type类造出来的"""
"""我们说默认情况下,所有的类的元类就是type"""
产生类的两种方式
1. class 类名
pass
2. 由于所有类的元类都是type,那么我们是不是也可以使用type创建类
type(object_or_name, bases, dict)
# 这三个参数是造出类的三个要素
type("类名","父类","类的名称空间")
3.为什么要学习元类?
"""
元类就是造出类的类,所以,我们使用type创建类可以为类定制化,一些办法
举个例子:
我让你写出来的类名必须是首字母大写?
思考:我们的定制化代码在哪里写呢?
类是如何产生的?类是有元类产生的type类,如果想改类的行为,应该在元类里的__init__方法中改.
对象是如何产生的? 是执行了产生这个对象的类内部的__init__方法
推导:已知推出来的未知.
"""
# 想改父类的__init__方法, 但是又不能修改源代码,所以我们可以写出来一个子类来继承父类type,在子类里面写代码,然后在从新执行一些父类的__init__方法.
Eg:
class Myclass(type):
def __init__(cls, cls_name, cls_bases=None, cls_dict=None):
# print(cls_name, cls_bases, cls_dict)
# A () {'__module__': '__main__', '__qualname__': 'A'}
if not cls_name.istitle():
raise Exception('首字母必须是大写')
super().__init__(cls_name, cls_bases, cls_dict)
# 元类不能直接被继承需要使用metaclass
class A(metaclass=Myclass):
pass
a = A()
class b(metaclass=Myclass):
pass
c = b()
# Exception: 首字母必须是大写
元类的进阶操作
__call__方法
# 对象加括号会自动调用类的__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') # 都是位置传参,强制要求必须是关键字传参
标签:__,Python,Mixins,元类,init,机制,type,class,cls
From: https://www.cnblogs.com/chao0308/p/17523203.html