Python中对象、类型、元类之间的关系
Python里的对象、类型和元类的关系很微妙也很有意思。
1989年圣诞节期间,上帝很无聊,于是创造了一个世界。
对象
在这个世界的运转有几条定律。
1.一切都是对象
对象(object)是这个世界的基本组成单位,所有的的事物都由对象构成。
什么是对象?不同的语言对对象的定义不尽相同。在Python的世界里,对象是数据的一种抽象表示。如果看了Python源码,事情就很好解释了,所有能通过PyObject类型的指针访问的都是对象。整数、字符串、元组、列表、字典、函数、模块、包,栈等都是对象。
圣经中提到,
2.所有对象都有三种特性: id、类型、值
id是一个对象的编号,每个对象天生都有一个与众不同的编号(目前实现是对象的地址).用id()能看到对象的id
>>> type(1) <type 'int'> >>> class A(object): pass ... >>> a = A() >>> type(a) <class '__main__.A'>
值是对象的价值所在。各种各样的对象保存着各种各样的值,Python的世界才会如此多彩。有的对象值永远不会变,叫不可变对象(immutable);有的对象值可以变,叫可变对象(mutable)。
再说一次:Python世界里,一切都是对象
类型
类(class)就是生产出对象的模具(本文只讨论new-style class,classic class不在讨论范围内)。上面说到,每个对象天生都会有个铭牌,写着自己的类型。在Python里,类(class)和型(type)指的是同一件东西。汉字真是精妙,类和型放在一块念是多么的自然。
3.每个对象都是由对应的类创建出来的
由这个定律很容易理解上文说到的,每个对象都有对应类型。类很像工厂里生产产品的模具,它负责对象的创建,决定了对象将被塑造成什么样,有什么属性、函数。
类可以继承和派生。虽然有点勉强,但姑且这么理解吧。类型B继承类型A,就像相当于模具B是以模型A为原型做出来的。生产出模具B的不是模具A,但模具B是模仿模具A而生产出来的,模具B生产出来的对象拥有模具A生产出来的对象类似的特性。模具B如果以模具A为原型生产出来,模具B身上会络上模具A的版权标识(?就当做版权保护吧)。用B.bases可以看模具B的印记。聪明的你可能已经注意到了,bases是复数,也就是说模具B可以以多个模具为原型,即多重继承。
>>> id(A) 140548933792976 >>> type(A) <type 'type'> >>> dir(A) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
可以看到,类型也像其他对象那样,有id,有类型,有值。它可以当变量、类成员、函数参数。有意思吧?更有意思的在后头。
定律3说到,任何对象都是由类型创建出来的。那类型这种对象是由谁创建出来的呢?继续拿模具来说,生产模具的模具是谁呢?模具的模具:元类(metaclass)。元类跟其它模具不同之处在于,它生产出来的是不是一般的对象,是模具。是不是很神奇?有了元类我们就可以在程序运行时动态生成类了。我们可以根据各种数据和配置,动态地定制我们所需要的类。这里不讨论元类的使用方法。不过元类除了能生产模具之外,跟其它模具相比无其它特别的地方。
有趣的问题又来了,根据定律1,元类也是对象吧,元类是谁生产出来的?元类是模具,生产模具的模具还是元类,所以元类的类型也应该是元类。继续追问下去,元类的元类的元类也是元类……这么追溯到源头(再强调一下,本文只讨论new-style class),就是一个特殊的元类:type。什么?type不是个查看类型的函数吗?通过help(type)可以知道,type是个类。type()如果传1个对象进去,type会返回这个对象的类型,这是我们熟知的用法;如果传3个对象进去,会生产出一个新的类出来。为什么会把两个功能放到一个类里做呢?可能是历史原因吧。再追问下去,这个终极的元类的类型是什么呢?上帝为了世界设定的统一,使type的类型是它自己。模具把自己生产出来了?这个下面讨论。
type引来的问题不只这些。
>>> object <type 'object'> >>> type <type 'type'> >>> type(object) <type 'type'> >>> type(type) <type 'type'> >>> type.__bases__ (<type 'object'>,)
我们看到,type这个模具是object为原型造的,而生产object的模具却是type。鸡先生蛋还是蛋先生鸡?Python这个世界是运行在虚拟机上的。世界创建之初虚拟机就把type和object都造出来了。object一出世,生产的模具就写着是type;type一出世,模板的版权印记就记着object。他们一开始就存在了,无所谓谁先谁后。同理,type是不是自己把自己创建也来的问题也一样。
总结
对象、类型、元类之间的关系
此文把对象、类型、元类的关系画成了这幅图。三个框分别表示元类、类型、一般对象。把虚线看成产品与模具的关系,实线看成模具与原型的关系,是不是一目了然?
Posted by Light Xue 2013-11-01
本作品由www.lightxue.com采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
相关推荐
-
Python编写ORM框架 python基础
2019-8-26
-
Python之变量的创建过程 python基础
2019-9-17
-
使用 tablib 来自动化管理测试用例,其他的工具都不用学了 python基础
2019-10-9
-
拼音纠错 python基础
2019-7-28
-
【AI实战】手把手教你实现文字识别模型(入门篇:验证码识别) python基础
2019-7-4
-
gunicorn syncworker 源码解析 python基础
2019-5-15
-
透析Python装饰器————-透过现象看本质 python基础
2019-8-25
-
基于异步IO框架Tornado的开源分布式博客blog_xtg python基础
2019-8-25
-
Python 图像处理 OpenCV (6):图像的阈值处理 python基础
2020-6-11
-
强大的 Python 任务自动化工具!invoke 十分钟入门指南 python基础
2020-5-31