旧式类 vs. 新式类(一)

转载须注明出处:@Orca_J35

旧式类 vs. 新式类(一)_第1张图片
目录.png

1. 概述

在 Python 中,类(class)和实例(instance)可被划分为两种风格:old-style (classic) 和 new-style。[^3]

在 Python 2 中为了保证兼容性,同时存在旧式类和新式类。

  • 如果继承列表为空,便会创建一个旧式类;
  • 如果继承旧式类,便会创建一个旧式类。
  • 如果继承"顶级类型" object,便会创建一个新式类;
  • 如果继承新式类(类型),便会创建一个新式类。

在 Python 3 中移除了旧式类,仅保留新式类。如果继承列表为空,便会创建一个继承自 object 的新式类。

tips: 在 Python 2 和3 中内置类型均是新式类。

>>> type(int)

>>> type(list)

2. Old-Style

在 Python 2.1 及其之前,只有旧式(old-style)类可用,并且 "类(class)" 和 "类型(type)" 是两个完全不相干的概念。

2.1 旧式类

classic class (in Glossary of Python 2)

Any class which does not inherit from object. See new-style class. Classic classes have been removed in Python 3.

在旧式类 OldCls 中,没有 __class__ 属性。type(OldCls) 的返回值表示 OldCls 的类型(type),且始终是 。由此可见,旧式类统一由一个独立的内置类型实现,即 types.ClassType (也称为 )。

如果旧式类没有显式继承任何旧式类,则其父类列表 __bases__ 为空。

>>> # in Python 2.7
>>> class OldCls: pass

>>>  # 旧式类没有__class__属性
>>> type(OldCls)

>>> OldCls.__bases__
()
>>> import types
>>> types.ClassType

# 旧式类OldCls是元类types.ClassType的实例
>>> isinstance(OldCls, types.ClassType)
True

a. ClassType in Python 2

types.ClassType 是 Python 2 中特有的内置类型,在 types 模块中的定义如下:

'''在Python2的types模块中,ClassType的定义如下'''
class _C:  # _C是旧式类
    def _m(self): pass
ClassType = type(_C)

types.ClassType 是继承自 object 的新式类(类型),其类型是 type:

>>> # in Python 2.7
>>> import types
>>> types.ClassType

>>> types.ClassType.__bases__
(,)
>>> type(types.ClassType)

>>> types.ClassType is type
False

types.ClassType 是旧式类的元类,负责构造旧式类,旧式类均是该元类的实例。所以,旧式类的类型均是 。另外,该类型也可构造新式类。

>>> # in Python 2.7
>>> # types.ClassType构造旧式类
>>> OldCls = types.ClassType('Other_OldCls', tuple(), dict())
>>> type(OldCls)

>>> OldCls.__bases__
()
>>> # types.ClassType也可构造新式类,此时和type等效
>>> NewCls = types.ClassType('X', tuple((object,)), dict())
>>> type(NewCls)

>>> NewCls.__bases__
(,)
>>>
>>> # type只能构造新式类,若第二参数为空,则默认继承object
>>> Other_NewCls = type('X', tuple(), dict())
>>> Other_NewCls.__class__

>>> Other_NewCls.__bases__
(,)

types.ClassType 不可以被继承,不能基于 types.ClassType 派生自定义元类。

>>> class Metaclass(types.ClassType):pass

Traceback (most recent call last):
  File "", line 1, in 
    class Metaclass(types.ClassType):pass
AttributeError: module 'types' has no attribute 'ClassType'

b. 三种等价定义方式

# in Python 2
class Old: pass

class Old:
    __metaclass__ = types.ClassType

Old = types.ClassType('Old', (), {})

2.2 旧式实例

对于某个旧式类的实例 x 而言,x.__class__ 表示 x 的类(class) ;而 type(x) 的返回值表示 x 的类型(type),且始终是 。由此可见,所有旧式实例与他们的类之间是相互独立的,旧式实例统一由一个独立的内置类型实现,即 types.InstanceType(也称为 "")

>>> # in Python 2.7
>>> class OldCls: pass

>>> OldCls().__class__

>>> type(OldCls())


>>> from types import *
>>> InstanceType
""

>>> # 旧式实例均通过InstanceType构造
>>> old_inst = InstanceType(OldCls)
>>> old_inst.__class__

>>> type(old_inst)

a. InstanceType in Python 2

types.InstanceType 是 Python 2 中特有的内置类型,在 types 模块中的定义如下:

'''在types模块中,InstanceType的定义如下'''
class _C: # _C是旧式类
    def _m(self): pass
_x = _C()
InstanceType = type(_x)

types.InstanceType 是继承自 object 的新式类(类型),其类型是 type,不能被继承

>>> # in Python 2.7
>>> import types
>>> types.InstanceType

>>> types.InstanceType.__bases__
(,)
>>> type(types.InstanceType)

通过 types.InstanceType 可为旧式类构造实例,但不会主动调用实例的 __init__ 函数。所以,用户定义旧式类的实例的类型均是

>>> in Python 2.7
>>> class OldCls:
    def __init__(self, a_str):
        self.a_str = a_str

>>> insts = OldCls("hello")
>>> type(insts)

>>> insts.__class__


>>> # types.InstanceType仅构造旧式类的实例,不会主动调用实例的__init__方法
>>> Other_insts = types.InstanceType(OldCls)
>>> type(Other_insts)

>>> Other_insts.__class__

>>> Other_insts.__init__("whale")
>>> Other_insts.a_str
'whale'
旧式类 vs. 新式类(一)_第2张图片
赞赏.jpg

你可能感兴趣的:(旧式类 vs. 新式类(一))