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

    • 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 的类可以非常轻量——甚至只包含 pass。这种"空类"在需要简单数据容器时非常有用,它通过属性访问语法(obj.x)提供了比字典更好的可读性。

空类作为数据容器

class Employee(object):
    pass

john = Employee()
john.name = "John Doe"
john.dept = "computer lab"
john.salary = 1000

print john.name     # John Doe
print john.dept     # computer lab

空类实例的 __dict__ 存储所有属性:

print john.__dict__
# {'salary': 1000, 'dept': 'computer lab', 'name': 'John Doe'}

与字典的对比

特性空类字典
语法obj.nameobj["name"]
键检查无(动态创建)KeyError
迭代obj.__dict__直接迭代
内存稍大稍小
可读性更好(模拟 struct)一般
# 字典写法
employee = {}
employee["name"] = "John Doe"
employee["dept"] = "computer lab"

# 空类写法
john = Employee()
john.name = "John Doe"
john.dept = "computer lab"

空类的 obj.name 语法更接近 C 的 struct 或 JavaScript 的对象,在表示结构化数据时更直观。

模拟抽象数据类型

空类可以模拟其他语言的数据结构:

class Point(object):
    pass

class Rectangle(object):
    pass

p1 = Point()
p1.x = 0
p1.y = 0

p2 = Point()
p2.x = 10
p2.y = 20

rect = Rectangle()
rect.top_left = p1
rect.bottom_right = p2

print rect.bottom_right.x     # 10

作为函数参数

空类可以替代需要特定接口的参数:

class FileLike(object):
    """模拟文件对象。"""
    pass

# 给空类添加必要的方法
content = StringIO("line1\nline2\nline3")
# StringIO 有 read() 和 readline(),可以传给需要文件对象的函数

def process_file(f):
    for line in f:
        print line.strip()

process_file(content)

Python 的"鸭子类型"哲学:不检查对象类型,只检查它是否有需要的方法。空类可以动态添加方法,实现这种灵活性。

命名元组 namedtuple

对于不可变的数据记录,collections.namedtuple 比空类更好:

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)

print p.x           # 3
print p.y           # 4
print p[0]          # 3,也支持索引

# 不可变
p.x = 10            # AttributeError: can't set attribute

namedtuple 自动生成 __init__、__repr__、__eq__ 等方法,内存占用也比普通类小,适合大量创建的数据记录。

使用建议

  • 需要可变数据记录 → 空类或普通类
  • 需要不可变数据记录 → namedtuple
  • 需要动态键 → 字典
  • 需要方法行为 → 完整类定义
  • 性能敏感且只读 → namedtuple 或 __slots__
上一页
魔术方法