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中对象、类型、元类之间的关系的更多相关文章

  1. python中对象、类型和元类之间的关系

    在python中对象.类型和元类构成了一个微妙的世界. 他们有在这个世界里和平共处,相辅相成.它们遵循着几条亘古不变的定律: 1.python中无处不对象 2.所有对象都有三种特性:id.类型.值 3 ...

  2. Python面向对象 | 类空间及类之间的关系

    一. 类的空间问题 1何处可以添加对象属性 class A: def __init__(self,name): self.name = name def func(self,sex): self.se ...

  3. php中对象类型与数组之间的转换

    1.刚看视频学习的时候看到一个困扰很久的问题, 有时候我们在进行做项目的时候会碰到的一个小问题.举一个小例子.  获取一个xml文件里面的数据. xml.xml文件如下: <?xml versi ...

  4. python摸爬滚打之day17----类与类之间的关系

    1.类与类之间的联系 1.1  依赖关系 类A中使用了类B, 类B作为参数传进类A的方法中被使用. 这种关系中类与类之间的联系是最轻的. class Elephant: def open(self,e ...

  5. Servlet中常用对象及API类之间的关系

    Servlet最常用的对象: 请求对象:ServletRequest和HttpServletRequest,通过该对象获取来自客户端的请求信息 响应对象:ServletResponse和HttpSer ...

  6. pygame中多个class类之间的关系

    用一个实例介绍一下有关pygame中不同类之间的通信,详细介绍在代码段有标注,感兴趣的可以复制代码试试: import pygame import sys # -------------------- ...

  7. 非常易于理解‘类'与'对象’ 间 属性 引用关系,暨《Python 中的引用和类属性的初步理解》读后感

    关键字:名称,名称空间,引用,指针,指针类型的指针(即指向指针的指针) 我读完后的理解总结: 1. 我们知道,python中的变量的赋值操作,变量其实就是一个名称name,赋值就是将name引用到一个 ...

  8. 小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系)

    小学生绞尽脑汁也学不会的python(面对对象-----类与类之间的关系 1. 依赖关系. 最轻的一种关系 在方法中引入另一个类的对象 class Elephant: def __init__(sel ...

  9. Python面向对象02/类的空间问题、类与对象之间的关系、类与类之间的关系

    Python面向对象02/类的空间问题.类与对象之间的关系.类与类之间的关系 目录 Python面向对象02/类的空间问题.类与对象之间的关系.类与类之间的关系 1. 类的空间问题 2. 类与对象之间 ...

随机推荐

  1. Pandas:从CSV中读取一个含有datetime类型的DataFrame、单项时间数据获取

    前言 有一个CSV文件test.csv,其中有一列是datetime类型,其他列是数值列,就像下边这样: 问题 1.读取该CSV文件,把datetime列转换为datetime类型,并将它设置为索引列 ...

  2. 【数据科学基础复习 - 3】PCA主成分分析

    本文仅就PCA原理及应用作一简单总结, 具体的数学原理等考试后再补上. 1. PCA推导 目标 对于正交空间中的样本点,现想将其投影到一个低维超平面中使得所有样本可在该平面中得到恰当的表达. 什么叫恰 ...

  3. Bugku CTF_web5

    1.打开网页,得到信息如下 2.打开hackbar,在body里传入post参数. 3.得到flag如下 4.主要考察以下几点: ->php无论是通过get请求还是post请求得到的数据都是字符 ...

  4. 阿里云CND加速

    1: :2: 3: 4: 5: 6: 7:将解析信息如实添加 8:如果报错添加 CNAME 记录提示和 A 记录冲突,也就是说如果你要添加 CDN 全站加速,域名解析那里就不能再有 A 记录了, 只有 ...

  5. 从零开始,开发一个 Web Office 套件(9):拖动鼠标选中文字 Edge Case

    这是一个系列博客,最终目的是要做一个基于 HTML Canvas 的.类似于微软 Office 的 Web Office 套件(包括:文档.表格.幻灯片--等等). 博客园:<从零开始, 开发一 ...

  6. html 两个并列div样式

    1.html 代码 <html> <head> <link rel="stylesheet" href="cs2.css"> ...

  7. 如何使用Java AWT 创建一个简易计算器

    摘要:手把手教你使用 Java AWT 创建一个简易计算器. 本文分享自华为云社区<手把手教你使用 Java AWT 创建一个简易计算器>,作者:海拥 . 关于AWT AWT (抽象窗口工 ...

  8. 使用Spring Data ElasticSearch+Jsoup操作集群数据存储

    使用Spring Data ElasticSearch+Jsoup操作集群数据存储 1.使用Jsoup爬取京东商城的商品数据 1)获取商品名称.价格以及商品地址,并封装为一个Product对象,代码截 ...

  9. redis哨兵功能

    redis哨兵功能 redis-Sentinel(哨兵) 前言 当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户都没有实现主从切换的功能 redis ...

  10. winform 代码生成textbox ,checkbox

    参考地址:https://jingyan.baidu.com/article/380abd0a6b80701d90192cde.html 首先搭建好Winform项目框架后,创建窗体页面后自行布局 这 ...