Python中类的概念
在理解什么是metaclass之前,先让我们了解一下Python中的普通类。Python对于什么是类有一个很特殊的概念。
在大多数的语言中,类就是一段代码,是用来创建对象的,这对Python也一样。例如:
class ObjectCreator(object):
pass
my_object = ObjectCreator()
print(my_object)
#执行结果
<__main__.ObjectCreator object at 0x0497B330>
但在Python中class还有更深的用意,即Class同样也是对象。
class ObjectCreator(object):
pass
当你使用关键字 class 时,Python执行后会创建一个OBJECT,即执行上述代码会在内存中创建“ObjectCreator”对象。
这个对象(class)本省就能创造实例(my_object)这就是为什么它是类。
但同时他也是一个对象,你可以用来:\
1.你可以把它分配给一个变量\
2.可以复制\
3.可以给它添加属性\
4.可以把它作为一个函数参数传递
print(ObjectCreator)#可以打印,因为他是一个对象
def echo(o):
print(o)
echo(ObjectCreator)#可作为参数传递
print(hasattr(ObjectCreator, 'new_attribute'))
ObjectCreator.new_attribute = 'foo' #增加属性
print(hasattr(ObjectCreator, 'new_attribute'))
print(ObjectCreator.new_attribute)
ObjectCreatorMirror = ObjectCreator #赋值给变量
print(ObjectCreatorMirror.new_attribute)
print(ObjectCreatorMirror())
下边是以上的输出
<class '__main__.ObjectCreator'>
False
True
foo
foo
<__main__.ObjectCreator object at 0x04DF22B0>
动态的创建class
可以在方法中动态的创建类
见以下代码:
>>> def choose_class(name):
... if name == 'foo':
... class Foo(object):
... pass
... return Foo # return the class, not an instance
... else:
... class Bar(object):
... pass
... return Bar
...
>>> MyClass = choose_class('foo')
>>> print(MyClass) # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print(MyClass()) # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>
但以上也不是很动态,因为依然要自己写整个类。思考一下,既然class是一个object,根据面向对象思想,他肯定是由什么东西创建的。当时用class关键字的时候,Python自动的创建了一个对象(之前说过),但是和Python中众多事情一样(暂时还不知道什么事),它可以手动创建。
我们来使用 type 函数观察一下object的类型。
>>> print(type(1))
<type 'int'>
>>> print(type("1"))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>
Amazing!我们看到 type 有完全不同的能力,它也可以动态地创建类。type 可以将类的描述作为参数,并返回一个类。让我们接着看type是怎么工作的:
type(name of the class,
tuple of the parent class (for inheritance, can be empty),
dictionary containing attributes names and values)
eg:
>>> class MyShinyClass(object):
... pass
可以手动被创建:
>>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print(MyShinyClass)
<class '__main__.MyShinyClass'>
>>> print(MyShinyClass()) # create an instance with the class
<__main__.MyShinyClass object at 0x8997cec>
type 接受一个字典来定义类的属性:
>>> class Foo(object):
... bar = True#自动创建
>>> Foo = type('Foo', (), {'bar':True})
>>> print(Foo)
<class '__main__.Foo'>
>>> print(Foo.bar)
True
>>> f = Foo()
>>> print(f)
<__main__.Foo object at 0x8a9b84c>
>>> print(f.bar)
True
当然也可以内敛与type中:
>>> class FooChild(Foo):
... pass
>>> FooChild = type('FooChild', (Foo,), {})
>>> print(FooChild)
<class '__main__.FooChild'>
>>> print(FooChild.bar) # bar is inherited from Foo
True
可以利用此特性向类中添加方法:
>>> def echo_bar(self):
... print(self.bar)
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True
这是Python利用关键字 class 能做的事,这些都是通过 ==metaclass== 实现的。
接下来让我们来看看什么是metaclass?
敲黑板!! 元类(metaclass)就是Python用来创造类的类
通过上边的学习我们知道Python中的class也是对象。\
而这些class就是metaclass创建的,class是metaclass的对象。
可以表示如下:
MyClass = MetaClass()
my_object = MyClass()
也可以表示如下:
MyClass = type('MyClass', (), {})
这是因为方法 type 实际上是一个元类,是Python用来在幕后创建所有类的。
有一点,之所以使用 type 而没用 Type 是因为这是一个与str的一致性的问题,这个类创造了字符串对象,并且int类创建了整型对象。type 就是创建类对象的类。
可以使用class 属性检测Python中的一切事物。我们会发现Python一切皆对象:
>>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>> foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
question? 那好奇宝宝要问了class 的 class是什么呢?
答案是:type
here we are:
>>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>
好了,相信到这里你已经明白了metaclass是什么了,如果乐意的话,你可以叫它“类工厂”。