元类
一.类也是对象
在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段,在python中这点任然成立,但是远不止与此,在python中,类同样也是对象,只要你使用关键字class,Python解释器在执行的时候就会创建一个对象。
class ObjectCreator(object): pass
这段代码会在内存中创建一个对象,名字就是ObjectCreator。这个对象(类对象ObjectCreator)拥有创建对象(实例对象)的能力。但是,它的本质仍然是一个对象,于是乎你可以对它做如下的操作:
- 你可以将它赋值给一个变量
- 你可以拷贝它
- 你可以为它增加属性
- 你可以将它作为函数参数进行传递
二.动态的创建类
1).因为类也是对象,你可以在运行时动态的创建它们,就像其他任何对象一样。首先,你可以在函数中创建类,使用class关键字即可。
def choose_class(name): if name == 'foo': class Foo(object): pass return Foo else: class Bar(object): pass return Bar Myclass=choose_class('foo') print(Myclass)#函数返回的是类,不是类的实例 print(Myclass())#可以通过这个类创建类实例,即对象
2).使用type创建类
type可以查看对象的类型,当使用type对ObjectCreator查看类型是type
type还有一种完全不同的功能,动态的创建类。
格式:type(类名,由父类名称“不是字符串”组成的元组(可以为空),包含属性的字典(名称和值))
dwx=type("dwx",(),{"age":10})#创建类dwx a=dwx() print(a.age)
- type的第2个参数,元组中是父类的名字,而不是字符串
- 添加的属性是类属性,并不是实例属性
使用type创建带有方法的类
def sum(self,a,b): return a+b test=type("test",(),{"sum":sum}) a=test() print(a.sum(1,2))
类方法与静态方法都一样
在Python中,类也是对象,你可以动态的创建类。这就是当你使用关键字class时Python在幕后做的事情,而这就是通过元类来实现的。
三.元类
元类就是用来创建类的东西
函数type实际上是一个元类。type就是Python在背后用来创建所有类的元类。
元类就是创建类这种对象的东西。type就是Python的内建元类
四.__metaclass__属性
可以在定义一个类的时候为其添加__metaclass__属性。
class Foo(object): __metaclass__=something
首先写下class Foo(object),但是类Foo还没有在内存中创建。Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类。
当写下如下代码时:
class Foo(Bar): pass
Python做了如下的操作:
- Foo中有__metaclass__这个属性吗?如果是,Python会通过__metaclass__创建一个名字为Foo的类(对象)
- 如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。
- 如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。
- 如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。
五.自定义元类
就元类本身而言,它们其实是很简单的:
- 拦截类的创建
- 修改类
- 返回修改之后的类
class UpperAttrMetaClass(type): # __new__ 是在__init__之前被调用的特殊方法 # __new__是用来创建对象并返回之的方法 # 而__init__只是用来将传入的参数初始化给对象 # 你很少用到__new__,除非你希望能够控制对象的创建 # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__ # 如果你希望的话,你也可以在__init__中做些事情 # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用 def __new__(cls, future_class_name, future_class_parents, future_class_attr): #遍历属性字典,把不是__开头的属性名字变为大写 newAttr = {} for name,value in future_class_attr.items(): if not name.startswith("__"): newAttr[name.upper()] = value # 方法1:通过'type'来做类对象的创建 # return type(future_class_name, future_class_parents, newAttr) # 方法2:复用type.__new__方法 # 这就是基本的OOP编程,没什么魔法 # return type.__new__(cls, future_class_name, future_class_parents, newAttr) # 方法3:使用super方法 return super(UpperAttrMetaClass, cls).__new__(cls, future_class_name, future_class_parents, newAttr)
class Foo(object, metaclass = UpperAttrMetaClass):