Python中对象、类型、元类之间的关系
Python里的对象、类型和元类的关系很微妙也很有意思。
1989年圣诞节期间,上帝很无聊,于是创造了一个世界。
对象
在这个世界的运转有几条定律。
1.一切都是对象
对象(object)是这个世界的基本组成单位,所有的的事物都由对象构成。
什么是对象?不同的语言对对象的定义不尽相同。在Python的世界里,对象是数据的一种抽象表示。如果看了Python源码,事情就很好解释了,所有能通过PyObject类型的指针访问的都是对象。整数、字符串、元组、列表、字典、函数、模块、包,栈等都是对象。
2.所有对象都有三种特性: id、类型、值
id是一个对象的编号,每个对象天生都有一个与众不同的编号(目前实现是对象的地址).用id()能看到对象的id
>>> id(1)
140657675012776
每个对象都会有类型(type),类型就像是商品上印的生产厂商一样,标识自己被谁生产出来。用type()可以看到对象的类型
>>> 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可以以多个模具为原型,即多重继承。
>>> class A(object): pass
...
>>> class B(A): pass
...
>>> A.__bases__
(<type 'object'>,)
>>> B.__bases__
(<class '__main__.A'>,)
这里注意,模具的版权标识跟对象的类型不一样。每个对象都会有类型,表示自己是哪个模具生产出来的。而模具的版权标识只有模具才会有,标识表示的是这个模具的设计原型哪个模具,并不表示这个模具是由这个原理模具生产出来的。
这里必须要提一下一个特殊的模具,堪称模具之母的模具:object。这个object不是上文说的对象,上文的对象是一个抽象的概念,这里的object是一个具体的模具。所有的模具(除了object自己)沿着印记向上追溯,最后肯定到object。也就是说,所有除了object自己以外的类,都直接或间接地继承了object,无论是内置的(buit-in)还是自定义的(user-defined)。另一方面看,所有对象都直接或间接由模具object生产出来。如果有兴趣的话,用type()把想查看对象的类型找到,再用__baess__向上查找,最后肯定会到object。从源码的角度看,object就是上文提到的PyObject。这跟Python里所有的对象都能用PyObject的指针访问是有关系的。
元类
定律1说到,一切都是对象,类型也是对象。相比很多语言,这一点非常特别。
>>> 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是不是自己把自己创建也来的问题也一样。
总结

此文把对象、类型、元类的关系画成了这幅图。三个框分别表示元类、类型、一般对象。把虚线看成产品与模具的关系,实线看成模具与原型的关系,是不是一目了然?
转自:http://www.lightxue.com/relationship-among-object-class-metaclass-in-python
Python中对象、类型、元类之间的关系的更多相关文章
- python中对象、类型和元类之间的关系
在python中对象.类型和元类构成了一个微妙的世界. 他们有在这个世界里和平共处,相辅相成.它们遵循着几条亘古不变的定律: 1.python中无处不对象 2.所有对象都有三种特性:id.类型.值 3 ...
- Python面向对象 | 类空间及类之间的关系
一. 类的空间问题 1何处可以添加对象属性 class A: def __init__(self,name): self.name = name def func(self,sex): self.se ...
- php中对象类型与数组之间的转换
1.刚看视频学习的时候看到一个困扰很久的问题, 有时候我们在进行做项目的时候会碰到的一个小问题.举一个小例子. 获取一个xml文件里面的数据. xml.xml文件如下: <?xml versi ...
- python摸爬滚打之day17----类与类之间的关系
1.类与类之间的联系 1.1 依赖关系 类A中使用了类B, 类B作为参数传进类A的方法中被使用. 这种关系中类与类之间的联系是最轻的. class Elephant: def open(self,e ...
- Servlet中常用对象及API类之间的关系
Servlet最常用的对象: 请求对象:ServletRequest和HttpServletRequest,通过该对象获取来自客户端的请求信息 响应对象:ServletResponse和HttpSer ...
- pygame中多个class类之间的关系
用一个实例介绍一下有关pygame中不同类之间的通信,详细介绍在代码段有标注,感兴趣的可以复制代码试试: import pygame import sys # -------------------- ...
- 非常易于理解‘类'与'对象’ 间 属性 引用关系,暨《Python 中的引用和类属性的初步理解》读后感
关键字:名称,名称空间,引用,指针,指针类型的指针(即指向指针的指针) 我读完后的理解总结: 1. 我们知道,python中的变量的赋值操作,变量其实就是一个名称name,赋值就是将name引用到一个 ...
- 小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系)
小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系 1. 依赖关系. 最轻的一种关系 在方法中引入另一个类的对象 class Elephant: def __init__(sel ...
- Python面向对象02/类的空间问题、类与对象之间的关系、类与类之间的关系
Python面向对象02/类的空间问题.类与对象之间的关系.类与类之间的关系 目录 Python面向对象02/类的空间问题.类与对象之间的关系.类与类之间的关系 1. 类的空间问题 2. 类与对象之间 ...
随机推荐
- 截图工具snipaste
下载地址: https://zh.snipaste.com/download.html 使用: 按F1截图,截图后按F3悬浮
- (转)oracle 数据库性能健康检查脚本
转至:https://blog.csdn.net/cm_0205/article/details/100210526?utm_medium=distribute.pc_relevant_downloa ...
- 分布式多线程 EOFError: Ran out of input
原因: 在将Queue注册到网上的时候,callable参数使用了lambda匿名函数,而Windows下绑定调用接口不能用lambda QueueManager.register('get_task ...
- net core or Linux
某用户执行net core sdk 版本不生效 sudo chmod +x /home/username/netcore3.1sdk/dotnet //某个用户执行新版本net core sdk
- Linux CentOS7.X-安装jdk
一.下载 jdk 的 tar 包 网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.h ...
- SQL从零到迅速精通【数据库应用】
数据库理论的研究主要集中于关系规范化理论和关系数据理论等.数据库技术与计算机技术的结合使得数据库中新的技术层出不穷.最初的数据库系统主要应用于银行管理.飞机订票等事务处理环境.后来渐渐应用于工程设计与 ...
- Open Babel的安装与使用
技术背景 Open Babel是化学领域常用的一个文件格式转换工具,它可以支持xyz的坐标格式.SMILES表达式.InChI表达式和mol以及mol2等格式之间的互相转化.比如说,你只有一个甲烷的S ...
- zabbix图形中文乱码
别的贴子都是说到修改/usr/share/zabbix/include/defines.inc.php中的 define('ZBX_FONT_NAME', 'msyh'); define('ZBX_G ...
- CF1500D Tiles for Bathroom (递推+大讨论)
题目大意:给你一个n*n的矩阵,现在问对于每个k\le n,求出所有k*k的子矩阵中,元素种类数不超过q的矩阵个数,n\le 1500, q\le 10 先考虑最暴力的做法: 对于每个格子,求出以它为 ...
- EasyExcel完成excel文件的导入导出
简介 常见的Excel分析框架有Apache poi 和EasyExcel, poi在另一篇已经介绍过了,详情可以看[https://www.cnblogs.com/jasmine-e/p/16064 ...