飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 第1章 认识Python

    • Python 历史与特点
    • Python 2 与 Python 3 的核心差异
    • 安装与运行 Python 2.7.18
    • 编码规范 PEP 8
  • 第2章 基础语法

    • 变量与对象
    • 数字类型
    • 字符串 str
    • Unicode 字符串
    • 运算符
    • 空值 None
  • 第3章 流程控制

    • if 条件语句
    • if-else 条件语句
    • if-elif-else 多分支
    • 条件表达式(三元运算符)
    • while 循环
    • for 循环
    • range 与 xrange
    • 循环控制:break、continue、pass
    • 循环 else 子句
  • 第4章 数据结构

    • 列表基础
    • 列表方法
    • 列表推导式
    • 元组
    • 字典基础
    • 字典方法
    • 字典循环技巧
    • 集合
    • 序列解包
    • 序列比较
  • 第5章 函数

    • 定义函数
    • 参数传递机制
    • 默认参数
    • 关键字参数
    • 可变参数
    • Lambda 表达式
    • 文档字符串
    • 函数对象
  • 第6章 模块与包

    • import 导入
    • 模块搜索路径
    • name 与主程序
    • 编译文件 .pyc 与 .pyo
    • 包结构
    • dir() 函数
  • 第7章 文件与IO

    • 打开与关闭文件
    • 文件读写方法
    • with 上下文管理器
    • 格式化输出:% 操作符
    • 格式化输出:str.format()
    • JSON 序列化
  • 第8章 面向对象

    • 类定义与实例化
    • init 构造方法
    • 类变量与实例变量
    • 方法调用与 self
    • 继承基础
    • 多重继承
    • 新式类与旧式类
    • 私有变量与名称改写
    • 属性装饰器 property
    • 类方法与静态方法
    • 魔术方法
    • 空类与数据记录
  • 第9章 异常处理

    • 异常类型
    • try-except
    • try-except-else-finally
    • 抛出异常 raise
    • 自定义异常
    • with 语句与上下文管理器
  • 第10章 迭代器与生成器

    • 迭代器协议
    • 生成器函数
    • 生成器表达式
    • itertools模块
  • 第11章 标准库精要

    • os模块
    • sys模块
    • datetime模块
    • re模块
    • json模块
    • collections模块
    • math与random模块
    • urllib2与网络请求
    • subprocess与命令执行
    • threading与并发
    • unittest与测试
    • 虚拟环境与包管理
  • 第12章 工程实践

    • 调试技巧
    • 性能分析
    • 文档与注释
    • 下一步学习

新式类与旧式类

Python 2 中存在两种类:旧式类(classic classes)和新式类(new-style classes)。这是 Python 2 最混乱的设计之一,也是 Python 3 彻底移除旧式类的原因。理解两者的区别,对写出正确的 Python 2 代码至关重要。

语法区别

# 旧式类(Python 2 默认)
class OldStyle:
    pass

# 新式类(必须显式继承 object)
class NewStyle(object):
    pass

print type(OldStyle())      # <type 'instance'>
print type(NewStyle())       # <class '__main__.NewStyle'>

旧式类不继承任何类(或者说继承自一个隐式的 instance 类型),新式类显式继承 object。

核心差异

特性旧式类新式类
类型type 'instance'type 'class'
MRO深度优先C3 线性化
super()不支持支持
__getattribute__不支持支持
property不支持支持
描述符不支持支持
__slots__不支持支持
多重继承行为不可预测行为明确

为什么旧式类存在

旧式类是 Python 1.x 的遗产。Python 2.2 引入新式类时,为了保持向后兼容,旧式类仍然作为默认行为保留。Python 3 中所有类都是新式类,旧式类被彻底移除。

实际影响

1. super() 不可用

class Base:
    def method(self):
        return "Base"

class Derived(Base):
    def method(self):
        # super(Derived, self).method()  # TypeError: super() argument 1 must be type, not classobj
        return Base.method(self) + " -> Derived"

旧式类中必须用 Base.method(self) 调用父类方法。

2. property 不可用

class Circle:
    @property               # 旧式类中 property 不工作!
    def area(self):
        return 3.14 * self.r ** 2

c = Circle()
c.r = 5
print c.area            # <property object>,不是计算结果!

旧式类中 property 只是返回 property 对象本身,不会拦截属性访问。

3. 方法解析顺序不同

class A:
    def method(self):
        return "A"

class B(A):
    def method(self):
        return "B"

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

d = D()
print d.method()        # B(旧式类深度优先)

旧式类的 MRO 是 D -> B -> A -> C,而新式类是 D -> B -> C -> A。

始终使用新式类

Python 2 中,始终显式继承 object:

# 正确
class Animal(object):
    pass

class Dog(Animal):
    pass

# 错误(旧式类)
class Animal:
    pass

这是 Python 2 编程的铁律。不继承 object 的类会失去 super()、property、描述符等现代特性,而且多重继承行为不可预测。

类型检查的差异

class Old:
    pass

class New(object):
    pass

o = Old()
n = New()

print type(o) == Old        # False!旧式类的 type 不是类本身
print type(n) == New        # True

print isinstance(o, Old)    # True
print isinstance(n, New)    # True

旧式类中 type(instance) == Class 不成立,因为 type() 返回 instance 而非类。始终用 isinstance() 进行类型检查。

向 Python 3 迁移

Python 3 中所有类都是新式类,以下代码在 Python 2 和 3 中都有效:

class Animal(object):
    pass

class Dog(Animal):
    pass

如果 Python 2 代码中有不继承 object 的类,迁移到 Python 3 时只需加上 (object),行为基本不变(除了 type() 返回值变化)。

上一页
多重继承
下一页
私有变量与名称改写