提出问题:
如何在一个类创建一个类呢?
首先我们的实现方式是这样的, 看下以下代码:
class A :
def create_class(self,user):
if user=="company":
class Company:
def __str__(self):
return "Company class"
return Company
if user=="school":
class School:
def __str__(self):
return "Company class"
return School
a=A()
Companyclass=a.create_class("company")
company=Companyclass()
print(company) # Company class
我们已经通过调用类的方法实现了 创建类,代码比较简单,我不做解释.不会的直接@我.
虽然我们实现了,但是代码量真是太大了. 我们再简洁点也可以把 类A删除掉,直接用方法就行了.
我们还有更好的方法直接创建类对象(类也是对象,方法和实例都可以称为对象)
Type 动态创建类
我们一定知道了,当我们调用type(1) 这个方法,可以进行类型查找. 它还有另外一个用法
就是创建类, 打个比喻 我们在做蛋糕, 必须用模板, 其中模板就是类,蛋糕是模板的实例.
但是蛋糕的模板 需要机器加工, 加工模板的机器就是 元类,它把模板当做机器的对象.
先看语法 :
Company=type(“类名称”,(继承的基类),{类的属性 })
Company=type("Company",(),{})
print(Company) # <class '__main__.Company'>
已经完成了 类的创建,只是继承的基类和 类的属性 全部为空.
我们再进一步扩展添加一些属性
Company=type("Company",(),{"name":"ebaotech","Adress":"杨浦区"})
co=Company()
print(co.name,co.Adress) #ebaotech 杨浦区
有细心的小伙伴该说了,类有属性也有方法, 怎么添加方法呢
我们就添加个方法试试 :
def run(self):
return "i am running"
Company=type("Company",(),{"name":"ebaotech","Adress":"杨浦区","run":run})
co=Company()
print(co.name,co.Adress,co.run())
解释要点
1.run 方法里必须有self ,不然用对象调用会找不到
2.“run”:run ,这个run 不要写成 run()的形式
添加继承基类
class Baseclass:
def say(self):
print("basecalss say")
def run(self):
return "i am running"
Company=type("Company",(Baseclass,),{"name":"ebaotech","Adress":"杨浦区","run":run})
co=Company()
co.say() #basecalss say
注意点 在添加继承类的时候,Baseclass 后边要有逗号,否则会报错.
自己写的平常的类,和type 生成的类实际都是一样的,平常的类也是会用type生成的.
这样就完成了, 又引出一个概念,什么是元类
元类就是创建类的类 ,刚才的type 就是一个元类.
解释下:既然我们已经介绍了,类也是对象 ,那谁去创建类对象呢,只能用元类.
元类控制过程
控制类对象生成过程用的是 metaclass 这个是在类对象生成之前进行的动作.
class Metaclass(type):
pass
class A(metaclass=Metaclass):
pass
为什么会控制类实例化过程呢 请看下边的解释.
Python做了如下的操作:
A中有metaclass这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Metaclass(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
一句话就是类里有 metaclass 就是运行metaclass 类,实在找不到就用type 去生成 .
现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以, metaclass 也是继承type .
自定义元类
请记住,'type’实际上是一个类,就像’str’和’int’一样
所以,你可以从type继承
class Metaclass(type):
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
class A(metaclass=Metaclass):
def __init__(self,name):
self.name=name
def __str__(self):
return " i love you "
a=A("Tengfei")
print(a) # i love you
class A 类对象操作实现委托给了 metaclass.
但就元类本身而言,它们其实是很简单, metaclass 三部曲:
-
拦截类的创建 (metaclass)
-
修改类 (在new里面修改)
-
返回修改之后的类 (return class )
具体的详情可以参考一下的链接:
深度理解python 元类