元类引入
在多数语言中,类就是一组用来描述如何生成对象的代码段,在python中同样如此,但是在python中把类也称为类对象,是的,你没听错,在这里你只要使用class关键字定义了类,其解释器在执行时就会创建一个对象,但是这个对象比较特殊,它可以创建自己的实例对象(像其他语言一样)。你可以对它进行下面的操作:
- 你可以将它赋值给一个变量
- 你可以拷贝它
- 你可以为它增加属性
- 你可以将它作为函数参数进行传递
动态创建类
听起来python在这方面跟一些语言的差别了吧,没错它还可以在运行时动态地创建它们,你可以在函数中创建类,用class关键字即可。
def choose_class(name): |
如果你想知道python中的变量或者数值的类型,你可以用万能而强大的type,如下(注意它们的返回值)print type(1) #数值的类型
<type 'int'>
print type("1") #字符串的类型
<type 'str'>
print type(ObjectCreator()) #实例对象的类型
<class '__main__.ObjectCreator'>
>>> print type(ObjectCreator) #类的类型
<type 'type'>
使用type创建类
创建格式:type(类名, 由类名称组成的元组( 针对继承的情况,可以为空),包含属性的字典( 名称和值) )
可以像这样创建:
Test2 = type("Test2",(),{}) #定了⼀个Test2类 |
上面等价于
class Test2: |
使用type创建带有属性的类
Foo = type('Foo', (), {'bar':True}) |
可以翻译为
class Foo(object): |
这个类跟普通创建的类一样使用,如继承这个类,你可以用下面的方法
'FooChild', (Foo,),{}) FooChild = type( |
同样等价于
class FooChild(Foo): |
注意:添加的属性都是类属性,第二个参数是继承自哪儿,采用元组的形式,也要知道在python中元组中只有一个参数表示方法只能是(xx,),而不能是(xx)
使用type创建带有方法的类
如果你想为你的类增加方法,那么你创建一个签名函数,然后添加其为属性赋值即可。
添加实例方法
In [46]: def echo_bar(self): #定义了⼀个普通的函数 |
添加类方法
In [42]: @classmethod |
添加静态方法
In [36]: @staticmethod |
看到这么多实现动态类的方法,你该明白python是怎么做到的,在这里就涉及到元类,元类就是用来创建类的东西,而创建类就是为了创建类的实例对象,所以可以这样理解,元类就是为了创建类对象的,而type实际上就是一个元类,传统类的元类就是types.classType,在 python中元类的介绍中也介绍了元类,有兴趣的读者可以去看看。SO,结论就是Python中所有的东西, 注意, 我是指所有的东西——都是对象。 这包括整数、 字符串、 函数以及类。 它们全部都是对象,并且它们都是从一个类创建而来, 这个类就是type。
metaclass属性
你也可以定义自己的元类,用到的就是上面的属性,首先,你可以在定义⼀个类的时候为其添加metaclass属性。
class Foo(object): |
那么当python解释器看到下面代码时
class Foo(Bar): |
做了如下的操作:
- Foo中有metaclass这个属性吗? 如果是, Python会通过metaclass创建⼀个名字为Foo的类(对象)
- 如果Python没有找到metaclass, 它会继续在Bar( ⽗类) 中寻找metaclass属性, 并尝试做和前⾯同样的操作。
- 如果Python在任何⽗类中都找不到metaclass, 它就会在模块层次中去寻找metaclass, 并尝试做同样的操作。
- 如果还是找不到metaclass,Python就会⽤内置的type来创建这个类对象。
在这个metaclass中可以放一些什么代码呢?——可以做任何涉及到类操作的事情,用type或者其子类来完成。
下面是用自定义类来当做元类
#coding=utf-8 |
f = Foo() |
其实简单地来讲,python中的元类用处一般就是下面三个
- 拦截类的创建
- 修改类
- 返回修改之后的类
哈哈,我想说的是对于元类咱们99%的人不会用到。