码迷,mamicode.com
首页 > 编程语言 > 详细

Python中的元类(译)

时间:2014-10-26 16:58:14      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   使用   sp   

add by zhj: 这是大stackoverflow上一位小白提出的问题,好吧,我承认我也是小白,元类这块我也是好多次想搞明白,

但终究因为太难懂而败下阵来。看了这篇文章明白了许多,再加下啄木鸟社区的 Python 类型和对象  这篇文章。卧槽,

这简直就是珠联璧合,日月神剑啊,尼玛。终于干掉了元类。翻译时有修改,建议与原文一起看。

原文:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python?answertab=votes#tab-top

类是对象

      在理解元类之前,你需要先掌握Python中的类。在Python中,对类的定义比较特殊,这点借鉴了Smalltalk语言。在大多

数语言中,类只是用于描述如何创建对象的代码片,在Python中,在一定程度上也是这样:

>>> class ObjectCreator(object):
...       pass
... 

>>> my_object = ObjectCreator()
>>> print(my_object)
<__main__.ObjectCreator object at 0x8974f2c>

不过,Python中的类不止如此。类也是对象,是的,我没说错。

当你使用关键字class时,Python解释器执行时,会创建一个对象。如下,Python会在内存中创建一个对象,并在符号表

中增加一个标识符ObjectCreator,指向那个对象,这就是Python中所说的引用,我们也常称之为变量。

>>> class ObjectCreator(object):
...       pass
... 

我们称这个对象为类对象,因为该对象可以实例化,创建实例对象,因此我们称它为类。

因为它是一个对象,所以:

  • 可以将它赋给一个变量
  • 可以copy它
  • 可以给它增加属性
  • 可以将它作为函数参数

比如

>>> print(ObjectCreator) # 可以print it
<class __main__.ObjectCreator>
>>> def echo(o):
...       print(o)
... 
>>> echo(ObjectCreator) # 类对象作为函数参数
<class __main__.ObjectCreator>
>>> print(hasattr(ObjectCreator, new_attribute))
False
>>> ObjectCreator.new_attribute = foo # 增加类的属性
>>> print(hasattr(ObjectCreator, new_attribute))
True
>>> print(ObjectCreator.new_attribute)
foo
>>> ObjectCreatorMirror = ObjectCreator # 赋值给另一个变量
>>> print(ObjectCreatorMirror.new_attribute)
foo
>>> print(ObjectCreatorMirror())
<__main__.ObjectCreator object at 0x8997b4c>


通过type类动态创建类

      其实,类对象也是实例化的结果,即类对象是由另一个类实例化得到的,我们称该类为元类,即元类是产生类的类,反之也成立,

如果类X实例化后得到是类对象,那X就是元类。在Python中,只有type类及其子类才可以当元类。多说一句,这里会有鸡生蛋、

蛋生鸡的问题。在Python中,一切都是对象,一切对象都是类实例化的结果。对象由类实例化得到,而类也是对象,它也是由类(元类)

实例化得到,继续向上,元类也是对象,也要由另一个元类实例化得到,这样下去就没有尽头了。在Python中,这个追溯终止在type类。

元类是type类或其子类,而type类的元类就是它自己,哈哈,type类自己创建自己,牛逼吧,当然type类的这个特性是Python设计者

guido van rossum等人设计并实现的。至于Python解释器是怎么找到元类的,后面我们会讲。

      还记得type()方法吗?我们常用它看一个对象X所属的类,即创建该对象X的类,当对象X是类对象时,看到的就是元类。如下,

>>> print(type(1))
<type int>
>>> print(type("1"))
<type str>
>>> print(type(ObjectCreator))     #查看创建ObjectCreator类的类
<type type>
>>> print(type(ObjectCreator()))
<class __main__.ObjectCreator>

      type类还有另外一个功能,它可以创建类,将类的一些信息做为type()的参数,并返回一个类。我知道,type根据输入参数的不同而有不同的功能,

这种做法是愚蠢的。当type()只有一个参数时,它的功能就是返回创建该参数对象的类;当多于一个参数时,type()才是type类的实例化,实例化得到

一个类并返回该类。type创建类时,参数格式如下,classname是类名,字符串类型,parentclasses是类所有父类,元组类型,attrs是类的所有{属性:值},

字典类型。

type(classname, parentclasses , attrs)

比如,

>>> class MyShinyClass(object):
...       pass

当解释器执行时,会转为下面的语句,当然,你也可以直接这么写。

MyShinyClass = type(MyShinyClass, (object,), {})

下面我们来定义一个类,并在类中定义属性,如

>>> 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

我们可以用另一个类继承它,so:

>>>   class FooChild(Foo):
...         pass

would be:

>>> FooChild = type(FooChild, (Foo,), {})
>>> print(FooChild)
<class __main__.FooChild>
>>> print(FooChild.bar) # bar is inherited from Foo
True

OK,你会想给你的类增加方法。定义一个函数,并将它分配给类的属性

>>> 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创建类都是这么简单吗?都是直接用type元类实例化得到?

不是的,你可以指定元类,这就是__metaclass__属性。

 

什么是元类

元类就是创建类的类(话说作者说话够罗嗦的,当然,对于小白来说,多说几次才能看明白)

在上面,我们提到可以使用type()查看创建一个对象的类,你也可以使用__class__,如下

>>> 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>

 

那__class__.__class__是什么呢?__class__返回的是一个类对象,再一次__class__返回的就是元类,如下

,下面这个结论并不具备普适性,有些类的元类并非元类。当然,如果你一直调用__class__,在有限次之后,

它返回的就一直是type类了。

>>> age.__class__.__class__
<type type>
>>> name.__class__.__class__
<type type>
>>> foo.__class__.__class__
<type type>
>>> b.__class__.__class__
<type type>

 

什么是元类

 

Python中的元类(译)

标签:style   blog   http   color   io   os   ar   使用   sp   

原文地址:http://www.cnblogs.com/ajianbeyourself/p/4052084.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!