返回介绍

建议54:理解 built-in objects

发布于 2024-01-30 22:19:09 字数 2688 浏览 0 评论 0 收藏 0

我们知道Python中一切皆对象:字符是对象,列表是对象,内建类型(built-in type)也是对象;用户定义的类型是对象,object是对象,type也是对象。自Python2.2之后,为了弥补内建类型和古典类(classic classes)之间的鸿沟 [1]引入了新式类(new-style classes)。在新式类中,object是所有内建类型的基类,用户所定义的类可以继承自object也可继承自内建类型。

那么内建类型﹑object﹑type以及用户所定义的类之间到底有什么关系呢?它们之间本质上有什么不同吗?我们来看一个简单的例子:

class A:          ... ... ... ... ... ... ... ... 
①古典类A
     pass
class B(object):
     pass
class C(type):
     pass
class D(dict):      ... ... ... ... ... ... ... ... 
②D
继承自内建类型dict
     pass

现在有类A﹑B﹑C﹑D的实例分别对应为a﹑b﹑c﹑d,我们来看一组求值的结果,如表6-1所示。

表6-1 不同对象求值结果

注:上表中求值时*用表中第一列的元素代替。

从表6-1中我们可以得出如下结论:

object[1]和古典类[3]没有基类,type[2]的基类为object。

新式类([4],[5],[6])中type()的值和__class__的值是一样的,但古典类[3]中实例的type为instance,其type()的值和__class__的值不一样。

继承自内建类型的用户类的实例[6]也是object的实例,object[1]是type的实例,type实际是个元类(metaclass)。

object和内建类型以及所有基于type构建的用户类[5]都是type的实例。

在古典类中,所有用户定义的类的类型都为instance。

综上,不同类型的对象之间的关系如图6-1所示。

图6-1 不同类型对象的关系图

我们知道古典类和新式类的一个区别是:新式类继承自object类或者内建类型。那么是不是可以这么理解:如果一个类定义的时候继承自object或者内建类型,那么它就是一个新式类,否则则是古典类?我们来看一个例子:

>>> class TestNewClass:
...  __metaclass__ = type   ... ... ... ... 
①设置__metaclass__
属性为type
...
>>>
>>> type(TestNewClass)
<type 'type'>
>>> TestNewClass.__bases__
(<type 'object'>,)
>>>
>>> a= TestNewClass()
>>> type(a)
<class '__main__.TestNewClass'>
>>> a.__class__
<class '__main__.TestNewClass'>
>>> 

从上述例子我们可以看出,TestNewClass在定义的时候并没有继承任何类,但测试的结果表明其父类为object,它还是属于新式类。这其中的原因在于TestNewClass中设置了__metaclass__属性(关于元类的更多介绍可以参看后面的章节)。所以我们并不能简单地从定义的形式上来判断一个类是新式类还是古典类,而应当通过元类的类型来确定类的类型:古典类的元类为types.ClassType,新式类的元类为type类。

新式类相对于古典类来说有很多优势:能够基于内建类型构建新的用户类型,支持property和描述符特性等。作为新式类的祖先,Object类中还定义了一些特殊方法,如:__new__(),__init__(),__delattr__(),__getattribute__(),_setattr__(),__hash__(),__repr__(),__str__()等。object的子类可以对这些方法进行覆盖以满足自身的特殊需求,建议62中会对其中某些内容详细阐述,感兴趣的读者可以阅读。

注意

在Python中一切皆对象,type也是对象。

[1] 这里的鸿沟指的是:在2.2版本之前,类和类型并不统一,如a是古典类ClassA的一个实例,那么a.__class__返回‘class__main__ClassA’,type(a)返回<type 'instance'>。当引入新类后,比如ClassB是个新类,b是ClassB的实例,b.__class__和type(b)都是返回‘class'__main__.ClassB’。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文