元类
type:创建类的类,称之为元类
class A():
pass
a = A()
print(type(a)) #<class '__main__.A'> # 实例所属的类
print(type(A)) #<class 'type'> # A类所属的类
print(type(type)) #<class 'type'> # 元类所属的类
type创建类
- 语法:
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值)) - 创建类:
MyClass = type(‘MyClass’, (), {})
函数type实际上是一个元类, type就是Python在背后用来创建所有类的元类(类工厂)
如:1 -> int -> type
type就是Python的内建元类,我们也可以创建自己的元类。
class Animal():
def __init__(self, name):
self.name = name
def eat(self):
print("i am eating...")
def eat(self): # 注:属性/方法 写在外面
print("dog is eating...")
def __init__(self, name):
self.name = name
###type语法创建类,第1个参数是 类名,第2个参数 是继承关系(元组形式),第3个参数是 属性和方法(字典形式)
Dog = type("Dog",(Animal,),{"eat":eat}) # 注:使用type语法去创建类
dog = Dog("peiqi")
dog.eat()
#结果为 dog is eating...
#创建Animal类
Animal = type("Animal",(object,),{"eat":eat,"__init__":__init__})
面向对象里有俩种关系:
继承关系: object 是所有类的父类,是最顶层的类
实例与类的关系: 创建关系 type就是最顶层的类,就是元类
自定义元类
class MyMeta(type): # 注:继承type
def __init__(self, *args):
print("test my metaclass") # 注:初始化时输出
class Foo(metaclass=MyMeta): # 注:默认参数是type 使用MyMeta创建Fool
def __init__(self):
print("Fool__init__")
#结果为 test my metaclass
print(Foo.__bases__) # 注:Foo的__bases__是 object
#结果为 (<class 'object'>,)
自定义元类,为每个类创建一个func方法,这个方法输出当前创建的类有哪些属性
class MyMate(type):
def __new__(cls, name, bases, attrs):
attrs["func"] = cls.func
return type.__new__(cls, name, bases, attrs)
def func(self):
return dir(self)
class A(metaclass=MyMate):
age = 10
a = A()
print(a.func())
# ['__class__', '__delattr__', '__dict__', '__dir__',...]
元类的主要目的就是为了当创建类时能够自动地改变类
·拦截类的创建
·修改类
·返回修改之后的类
拦截创建类
元类可以规定类创建时候的一些行为,拦截类创建的,对类设置做规范时
class MyMeta(type): # 注:继承type
def __new__(cls, name, bases, attrs): # 注:在__new__里面管理创建它 需要接收参数 这样传递(因为要把attrs捞出来判断)(或者可变长位置参数传递)
if "name" not in attrs:# 注:属性是字典类型的参数 type创建需要传递三个变量
raise TypeError("必须设置属性name")
attrs["test"] = "my mate test"
return type.__new__(cls, name, bases, attrs) # 注:元类里使用type的__new__去返回创建 把这些参数传递进去
# 注:不可能自己创建__new__的方法,使用type的__new__去创建
class A(metaclass=MyMeta): # 注:用自定义元类去创建
name = "wy"
#结果为 raise TypeError("必须设置属性name") # 注:A类中没有设置name属性时
# TypeError: 必须设置属性name
a = A() # 注:A的父类是object
print(a.test)
#结果为 my mate test
#把传进来的属性 先交给MyMeta去创建/添加 最后再交给type去创建
抽象基类
定义了接口规范
子类必须实现父类里的抽象方法
抽象基类不能实现实例化
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod # 被装饰器装饰的方法
def eat(self): # 抽象方法
pass # 抽象方法不需要具体的实现
def drink(self):
pass
class Dog(Animal):
# pass
def eat(self):# 该方法没被重写就会报错
print("dog is eating...")
d = Dog() # 实例化的时候,子类必须实现父类里面的抽象方法
# 如果没实现,会报TypeError: Can't instantiate abstract class Dog with abstract method eat
d.eat()
#结果:dog is eating...
# a = Animal() #注:报错 抽象基类不可以实例化