<< >>

diveintopython.org |

Python for experienced programmers

## 3.2. 定义类

Python是完全面向对象的：可以定义自已的类，从自已的或内置类进行继承，然后对生成的类进行实例化。

在Python中定义类很简单；就象定义函数，没有独立的定义接口。只要定义类，然后编码就可以了。Python类以保留字 `class` 开始，跟着是类的名字。从技术上说，有这些就足够了，因为一个类不需要从任何其它类继承而来。

例 3.3. 最简单的Python类

    class foo:
        pass

| 这个类的名字是 `foo`，它没有从任何其它的类继承而来。
| 这个类没有定义任何方法或属性，但是从语法上，需要在定义中有些东西，所以我们使用了 `pass`。这是一个Python保留字，仅仅表示“向前走，不要往这看”。它相当于C++中的大括号空集({})或者是Java中的单个分号。它是一条什么都不做的语句，当你删除函数或类时，它是一个很好的占位符。
| 你可能猜到了，在类中的每条语句都是缩排的，就象函数内的代码， `if` 语句， `for` 循环，等等。第一条不缩近的语句不属于这个类。

当然，实际上大多数的类将从其它的类继承来的，并且它们将定义自已的类方法和属性。但是如你所见，除了名字以外，没有什么东西是一个类必须拥有的。特别是，C++程序员可能会感到奇怪，Python的类没有明确的构造器和析构器。Python类的确存在同一个构造器相似的东西： `__init__` 方法。

例 3.4. 定义 `FileInfo` 类

    from UserDict import UserDict

    class FileInfo(UserDict):
        "store file metadata"
        def __init__(self, filename=None):
            UserDict.__init__(self)
            self["name"] = filename

| 类的祖先被列在立即跟在类名字后面的小括号里。所以 `FileInfo` 类是从 `UserDict` 类(这个类从 `UserDict` 中导入)继承而来。`UserDict` 是一个象字典一样动作的类，它允许你完全子类化字典数据类型，同时增加你自已的行为。(也存在相似的类 `UserList` 和 `UserString` ，它们允许你子类化列表和字符串。)在这个类的背后有一些“巫术”，我们将在本章的后面，随着更进一步地研究 `UserDict` 类，揭开这些秘密。
| 类也可以有文档字符串，就象模块和函数。
| `__init__` 在类的实例创建后立即被调用。它可能会诱使你，但是不正确地，叫它为类的构造器。说它诱使，是因为它看上去象构造器(按照习惯， `__init__` 是类中第一个定义的方法)，象构造器一样动作(在一个新创建的类实例中，它是首先被执行的代码)，并且听起来也象构造器(“init”当然意味着构造的本性)。说它不正确，是因为对象在 `__init__` 被调用的时刻已经被构造出来了，你已经有了对类的新实例一个有效的引用。
| 每一个类方法的第一个参数，包括 `__init__`，总是指向类的当前实例的一个引用。按照习惯这个参数被命名为 `self`。(除了 `self` 不要把它命名为别的东西，这是一个非常强烈的习惯。) `self` 象C++中的保留字 `this`。在 `__init__` 方法中， `self` 指向新创建的对象；在其它的方法中，它指向方法被调用的对象。
| `__init__` 方法可以接受任意个数的参数，就象函数一样，参数可以用缺省值定义，可以设置成对于调用者可选。在本例中， `name` 有一个缺省值 `None`，即Python的空值。
| 一些伪面向对象语言，象Powerbuilder有一种“扩展”构造器和其它事件的概念，即父类的方法在子类的方法执行前被自动调用。Python不这样做，你必须总是显示调用在父类中适合的方法。同样，当调用父类方法时，你必须包含 `self` 参数，跟着类方法所接受的任何其它类型。在本例中，我们没有使用参数(除了 `self`)调用 `UserDict` `类的 __init__` 方法。
| 我对你说过，这个类的象字典一样动作，那么这里就是第一个印象。我们将参数 `filename` 赋值给对象 `name` 关键字，作为它的值。
| 注意 `__init__` 方法从不返回一个值。

噢。我知道有很多知识需要吸收，但是你要掌握它。所有的Python类以相同的方式工作，所以一旦你学会了一个，就是学会了全部。再加上，在Python社区中有强烈的习惯，对于每个类方法的第一个参数都命名为“`self`”，所以你不会浪费大量时间去习惯他人的风格。如果你忘了别的任何事，也要记住这件事，因为我认定它会让你出错：

`__init__` 方法是可选的，但是一旦你定义了一个，就必须记得显示调用父类的 `__init__` 方法。这样更是正确的：何时一个子类想扩展父类的行为，后代方法必须在适当的时机，使用适当的参数，显式调用父类方法。

进一步阅读 |

- Learning to Program 有一个优雅的 类的介绍。
- How to Think Like a Computer Scientist 展示了如何 使用类来模拟复合数据类型。
- Python Tutorial 深入地考虑了 类，名字空间和继承。
- Python Knowledge Base 回答了 关于类的常见问题。

« 面向对象框架 | 实例化类 »