# 久韭

Keep it simple, stupid.

## 欢迎你，陌生人！

这个博客致力于从浩如烟海的复杂媒体形式中提取核心的知识内容，并以最基础的文字和图片形式展现。

← 在这里，没有复杂的分页跳转，只有最基础的目录导航。

*↖ 如果您使用的是移动端，请点击左上角的 ≡ 按钮打开目录。*


# 你真的“创建”了类吗？

Python 类创建流程解析

## 序——你真的会 `创建类` 吗？

> **类** 是 OOP（面向对象编程）的核心概念，更是 Python 中不可或缺的一部分。

日常中，我们天天都在用 Python 中的类，貌似相关内容已经没有什么新奇的了。

可是，你真的 **创建** 过类吗？

```python
class A(object):
    pass
a = A()
```

> 在 Python 中，类是由 class 语句定义的对象工厂，并由 type(obj) 内置函数返回。是一个动态的、运行时的概念。
>
> > In Python, classes are object factories defined by the class statement, and returned by the type(obj) built-in function. Class is a dynamic, runtime concept. [PEP 483](https://www.python.org/dev/peps/pep-0483/)

通常，我们所做的不过是用 `class` 来 **定义一个类**，而后利用它来 **创建实例对象**。

**准确地说，程序员仅是通过 `class` 设计了类，其余的工作交给解释器来完成。** **那么，具体的类创建又是如何完成的呢？**

在整理并深入研究了相关的 PEP、Python Reference 及各类博文的基础上，作者将通过本文解读 **Python 类创建的具体过程**。

{% hint style="warning" %}
**本文并非 Python 初级编程所需要了解的内容。**\
**理解本文需要扎实的 OOP 基础和 Python 高级编程经验。**
{% endhint %}

## 总——流程总览

1. **执行到类定义代码**
2. **解析 MRO 条目**
3. **确定适当的元类**
4. **准备类命名空间**
5. **执行类主体**
6. **创建类对象**
7. **准备执行后续代码**

![](/files/-Me_NfHcpFIUaKMkoalD)

## 分——分步解析

### 0. 执行到类定义代码

在检查到 `class` 关键字后，解释器开始进入创建类的流程中，此时的作用域也自然发生变化。

### 1. 解析 MRO 条目

#### 1.0 基类是 `type` 实例：

这种情况下 MRO 相关的内容涉及具体算法处理，比较复杂，请移步相关专题博文：

[Python“MRO 三定律”——关于 Python 中多继承 C3-MRO 算法的剖析](https://blog.csdn.net/WH2099/article/details/105118758)

#### 1.1 基类不是 `type` 实例：

如果在类定义中出现的基类不是 `type` 的实例，则使用 `__mro_entries__` 方法对其进行搜索，当找到结果时，它会以原始基类元组做参数进行调用。此方法必须返回类的元组以替代此基类被使用。元组可以为空，在此情况下原始基类将被忽略。

**考虑到在绝大多数情况下基类都是 `type` 的实例，且 1.1 所示的情况主要是为了支持泛型，本文不对 1.1 做过多深入，默认为 1.0 的情况。**

### 2. 确定适当的元类

为一个类定义确定适当的元类是根据以下规则：

#### 2.0 如果没有基类且没有显式指定元类，则使用 `type()`

#### 2.1 如果给出一个显式元类而且 不是 `type()` 的实例，则其会被直接用作元类

#### 2.2 如果给出一个 `type()` 的实例作为显式元类，或是定义了基类，则使用最近派生的元类

最近派生的元类会从显式指定的元类（如果有）以及所有指定的基类的元类（即 `type(cls)`）中选取。\
最近派生的元类应为 所有 这些候选元类的一个子类型。\
如果没有一个候选元类符合该条件，则类定义将失败并抛出 `TypeError`。

{% hint style="info" %}
*其实这个选取的方法与 C3 MRO 算法选取好头的操作是接近的。*
{% endhint %}

### 3. 准备类命名空间

一旦确定了适当的元类，则将准备好类命名空间。

#### 3.0 如果元类具有 `__prepare__` 属性：

如果元类具有 `__prepare__` 属性，它会以 `namespace = metaclass.__prepare__(name, bases, **kwds)` 的形式被调用（其中如果有任何额外的关键字参数，则应当来自类定义）。

*`__prepare__` 方法应该被实现为 `classmethod()`。*\
\&#xNAN;*`__prepare__` 所返回的命名空间会被传入 `__new__`，但是当最终的类对象被创建时，该命名空间会被拷贝到一个新的 `dict` 中*。

#### 3.1 如果元类没有 `__prepare__` 属性：

如果元类没有 `__prepare__` 属性，则类命名空间将初始化为一个 **空的有序映射**。

**PEP 模拟代码说明**

```python
def prepare_class(name, *bases, metaclass=None, **kwargs):
    if metaclass is None:
        metaclass = compute_default_metaclass(bases)
    prepare = getattr(metaclass, '__prepare__', None)
    if prepare is not None:
        return prepare(name, bases, **kwargs)
    else:
        return dict()
```

### 4. 执行类主体

类主体会以（类似于） `exec(body, globals(), namespace)` 的形式被执行。\
普通调用与 `exec()` 的关键区别在于当类定义发生于函数内部时，**词法作用域允许类主体（包括任何方法）引用来自当前和外部作用域的名称**。

{% hint style="info" %}
*这一点与 C++、Java 等语言大为不同，符合“显式优于隐式”的 Python 哲学。*
{% endhint %}

但是，即使当类定义发生于函数内部时，在类内部定义的方法仍然无法看到在类作用域层次上定义的名称。类变量必须通过实例的第一个形参或类方法来访问，或者是通过下一节中描述的隐式词法作用域的 `__class__` 引用。

### 5. 创建类对象

#### 5.0 元类

一旦执行类主体完成填充类命名空间，将通过调用 `metaclass(name, bases, namespace, **kwds)` 创建类对象（此处的附加关键字参数与传入 `__prepare__` 的相同）。

如果类主体中有任何方法引用了 `__class__` 或 `super`，这个类对象会通过零参数形式的 `super(). __class__` 所引用，这是由编译器所创建的隐式闭包引用。\
这使零参数形式的 `super()` 能够正确标识正在基于词法作用域来定义的类，而被用于进行当前调用的类或实例则是基于传递给方法的第一个参数来标识的。

**当使用默认的元类 `type` 或者任何最终会调用 `type.__new__` 的元类时，以下额外的自定义步骤将在创建类对象之后被发起调用:**

1. 首先，`type.__new__` 将收集类命名空间中所有定义了 `__set_name__()` 方法的描述器；
2. 接下来，所有这些 `__set_name__` 方法将使用所定义的类和特定描述器所赋的名称进行调用；
3. 最后，将在新类根据方法解析顺序所确定的直接父类上调用 `__init_subclass__()` 钩子。

*请注意上面提到的 **描述器** 与常见的使用 `property` 创建的 **描述器属性** 并非是同一个概念。使用 `property` 创建的是描述器属性，其默认前提是描述器属性的定义与类的定义是 **同步一体** 的，因为`property` 生成的描述器属性必然位于类中，此时编写者能够掌描述器属性及其底层相关变量在类中的命名（parent 和 \_x）；但在使用纯粹的描述器时，描述器的定义与类的定义是 **异步分离** 的情况下，描述器属性的编写者就无法知晓描述器属性及其底层相关变量在类中的命名。*

**同普通类一样，在元类中魔法方法的调用顺序是 `__new__`=>`__init__`。**

### 6. 准备执行后续代码

在类对象创建之后，它会被传给包含在类定义中的 **类装饰器**（如果有的话），得到的对象将作为已定义的类绑定到 **局部命名空间**。

*当通过 `type.__new__` 创建一个新类时，提供以作为命名空间形参的对象会被复制到一个新的有序映射并丢弃原对象。这个新副本包装于一个只读代理中，后者则成为类对象的 `__dict__` 属性。*

**PEP 模拟代码说明**

```python
class NewType(type):
    def __new__(cls, *args, **kwargs):
        if len(args) != 3:
            return super().__new__(cls, *args)
        name, bases, ns = args
        init = ns.get('__init_subclass__')
        if isinstance(init, types.FunctionType):
            ns['__init_subclass__'] = classmethod(init)
        self = super().__new__
        (cls, name, bases, ns)
        for k, v in self.__dict__.items():
            func = getattr(v, '__set_name__', None)
            if func is not None:
                func(self, k)
        super(self, self).__init_subclass__(**kwargs)
        return self

    def __init__(self, name, bases, ns, **kwargs):
        super().__init__(name, bases, ns)

class NewObject(object):
    @classmethod
    def __init_subclass__(cls):
        pass
```

{% hint style="info" %}
*\_\_new\_\_ 特殊在虽然它是作为类方法的形式存在的（第一个参数是 cls），但事实上由于我们并没有用相关装饰器，所以它并不会自动为其调用传入第一个 cls 参数，我们如果要调用，就必须手动传入第一个 cls 参数。*
{% endhint %}

## 析——元类解析

### 元类存在的必要性

在 OOP 中，动态的类创建是偏向于底层的高级概念。\
OOP 的核心是 **“万物皆对象”** ，而类作为程序员设计并使用的基础工具，也应该被视为对象。\
那么自然，**类对象** 需要有他的类，而这个类就是 **元类**。\
元类是留给类设计者的最底层概念，在其之下的都属于具体语言的实现，不再是 OOP 应该关注的内容。

而相较于 Java 等语言的反射机制，Python 选择直接将一部分类的创建流程公开给程序员，无疑是秉承了 **“显示优于隐式”** 的哲学。\
尽管在平常的使用中普通程序员很少会直接去影响类的创建，但在很多复杂而神奇的包开发中这却是不可或缺的工具。\
而事实上这的确成为了 Python 的 **重要优势** 之一，至今元类的应用非常广泛，包括且不限于 \_枚举、日志、接口检查、自动委托、自动特征属性创建、代理、框架以及自动资源锁定/同步 \_等等。

### 元类使用中的问题

首先，**元类是一个相当复杂的概念**。即便你已经对此有所了解，但实际应用时总还是会出现各种各样的问题，而且这些个问题往往会是由于底层概念上的递归造成的。

其次，**没有自动方法可以组合元类**。如果要为一个类使用两个元类，则通常需要手动创建一个将这两个类合并在一起的新元类。\
这种需求常常使用户感到意外：从两个不同的库继承的两个基类继承突然增加了手动创建组合元类的必要性，通常情况下，人们对这些库的那些细节完全不感兴趣。\
如果一个库开始使用以前从未使用过的元类，这将变得更加糟糕。当库本身继续正常工作时，将这些类与另一个库中的类组合在一起的每个代码突然都失败了。

### 优化方式

尽管有多种使用元类的方法，但绝大多数用例可分为三类：

1. 在类创建后运行的一些初始化代码
2. 描述器的初始化
3. 保持类属性定义的顺序

事实上为了满足这些需求，我们 **未必就非用元类不可**。

通过对类的创建进行简单的 **挂钩** 就可以轻松实现前两个类别：

一个 `__init_subclass__` 挂钩初始化一个给定类的子类。\
创建类时，对类中定义的所有属性（描述符）调用 `__set_name__` 挂钩。

而第三个类别自从 Python 3.6 进行了 compact dict 的优化使 `dict` 类型默认保留插入顺序后，通过 `__prepare__` 也完全可以满足。

{% hint style="success" %}
**在当前的版本中，元类不再是我们深度定制类创建的唯一选择，活用以下这三个魔法方法，你就可以和元类说再见了：**

* `__init_subclass__`
* `__set_name__`
* `__prepare__`
  {% endhint %}

## 码——代码验证

{% hint style="info" %}

> Talk is cheap. Show me the code.
>
> 屁话少说，放码过来。
> {% endhint %}

```python
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
__author__ = 'WH-2099'

import sys
from pprint import pp

n = -1


class ExampleBaseclass(object):

    @classmethod
    def __init_subclass__(cls, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')


class ExampleMetaclass(type):

    def __new__(cls, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')
        return super().__new__(cls, *args, **kwargs)

    def __init__(cls, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')
        super().__init__(*args, **kwargs)

    @classmethod
    def __prepare__(metacls, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')
        return super().__prepare__(*args, **kwargs)


class ExampleClass(ExampleBaseclass, metaclass=ExampleMetaclass):

    global n
    n += 1
    print(f'[{n}] body of {__qualname__}')
    print('='*40, '\n')


    class Descriptor(object):

        def __get__(self, instance, owner):
            pass

        def __set_name__(self, owner, name):
            global n
            n += 1
            print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
            pp(locals())
            print('-'*80, '\n')


    descriptor = Descriptor()

    def __new__(cls, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        global n
        n += 1
        print(f'[{n}] {__class__.__qualname__}.{sys._getframe().f_code.co_name}\n')
        pp(locals())
        print('-'*80, '\n')
        super().__init__(*args, **kwargs)


example = ExampleClass()
```

> **强烈建议读者复制这段代码实际运行一下，这段代码的输出能让读者清晰地了解类创建地具体流程。**

## 参——参考资料

事实上，作者整理本文的过程中参考了大量的杂项资料，包括且不限于：

* 撤销或过时的 PEP
* cnblog 的解析博文
* csdn 的解析博文
* **······**

在此只列出 **优质且给予本文重要启发** 的部分。

1. [Python Reference（官方文档 - 语言参考）](https://docs.python.org/zh-cn/3/reference/datamodel.html)
2. [PEP 3115 -- Metaclasses in Python 3000](https://www.python.org/dev/peps/pep-3115/)
3. [PEP 487 -- Simpler customisation of class creation](https://www.python.org/dev/peps/pep-0487/)


# MRO 三定律

关于 Python 中多继承 C3-MRO 算法的剖析

*面向对象编程（OOP）的重要特性之一就是多态（或者说子类属性/方法覆写），一般通过以特定的顺序搜索对象的属性和方法来实现，该顺序被称为 Method Resolution Order (MRO)。本文展示了 Python 中 MRO 生成算法的具体实现，解析了其算法逻辑。*

## 0. 声明

{% hint style="warning" %}
**不从 `0` 开始难不成从 `1` 开始？你知道吗，世上只有 `10` 种人，程序员和非程序员;**
{% endhint %}

* **Keep it simple, stupid !**
* 仅代表个人观点，难免有缺漏之处，欢迎指正
* 本文假设您已经对 Python 中面向对象的基础内容有所掌握
* 本文有明确的主题，故默认顶层基类为 `object`（不涉及 `type` 有关内容）

## 1. 关于 MRO

### 1.0 什么是 MRO？

{% hint style="info" %}
**方法解析顺序（Method Resolution Order, MRO）** 是在 **面向对象编程** 中，当某个实例对象应用了继承，进而引发 **多态** 特性时，编译/解释器 **查找并决定具体实例方法的顺序** 。
{% endhint %}

根据子类继承的父类数量区分，MRO 会有两种情况：

1. 单继承中的 MRO —— 这种情况比较简单。
2. 多继承中的 MRO —— 这种情况相对复杂，并且随着类继承层次的混乱，复杂程度往往超乎想象。

一般情况下所提到的 MRO 基本都是指复杂多继承中的 MRO，其本质是 **一个顺序**，**可用具体编程语言中的序列来表示（Python 中就是 `collections.abc.Sequence`）**，本文同一般情况。

### 1.1 MRO 有什么用？

* 实现方法重载
* 构建 OOP 多态
* 保证继承有效

**简而言之，MRO 是 OOP（面向对象编程）的一根顶梁柱，没了它，OOP 的特性和优势都会大打折扣。**

关于 MRO 的作用，可以回顾一下 **OOP** 中关于 ***重载、继承、多态*** 的内容。

## 2. 关于 C3-MRO 算法

### 2.0 什么是 C3-MRO 算法？

{% hint style="info" %}
**C3 superclass linearization（C3 超类线性化算法），其本质是一个排序算法**，主要用于生成多继承 MRO（方法解析顺序）。
{% endhint %}

> 1996 年的 OOPSLA 会议上，论文 [*"A Monotonic Superclass Linearization for Dylan"*](https://doi.org/10.1145/236337.236343) 首次提出了 C3 超类线性化算法。随后被应用于 Python 2.3 中新式类的 MRO 解析。

为了便于叙述，本文中称之为 **C3-MRO 算法**（连字符分隔的后缀表示其实际应用领域）。

### 2.1 C3-MRO 算法与 Python 有什么关系？

Python 2.2 版本向 2.3 版本过度时，为了贯彻 OOP 的语言层级设计，在已有的`经典类`基础上新增了`新式类`。

{% hint style="info" %}
Python 3 中摒弃了经典类，仅留新式类，可以说 **新式类就是 Python 3 中默认使用的类** 。
{% endhint %}

关于两个类型的具体内容在此不做深究，但新式类有一个重要特性就是在未显式声明继承父类的情况下默认继承自`object`类，配合 Python 允许多继承的语法设计，初期为开发者们带来了不小的问题。勾出了不少隐居大佬掏出了珍藏的各种~~黑魔法~~现身江湖，但很不幸都没能获得足够的成效：

> [PEP 253The Python 2.3 Method Resolution Order](https://www.python.org/dev/peps/pep-0253/) [\[Python-Dev\] perplexed by mro](https://mail.python.org/pipermail/python-dev/2002-October/029035.html)

最终开发者们发现，其实早有学者研究出了合适的解决方案：1992 年苹果推出了 Dylan 语言，1996 年相关的论文提出了 C3 算法。\
于是 C3 算法在 2003 年临危受命，揽下了解决 Python 2.3 版本中`新式类`MRO 的烂摊子。

**时至 2021 年的 Python 3.9.6 版本，C3 算法仍是 Python 中解决多继承 MRO 问题的核心算法。**

{% hint style="warning" %}
*还真没听说过这 Dylan 语言 XD*
{% endhint %}

事实上，在 Python 中，你可以利用 `cls.__mro__` 或者 `cls.mro()` 获取类或对象的 MRO 序列，而这就是基于 C3-MRO 算法的：

```python
class A(object):
    pass
class B(A):
    pass

print(B.__mro__)
# (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
print(b.mro())
# [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

# 二者的区别在于返回的分别是 tuple 和 list
```

## 3. C3-MRO 算法思路剖析

{% hint style="warning" %}
以下内容建立在作者的理解上，**带有浓重个人色彩，难免缺乏客观度** 。

但个人认为这样思路**相对自然**，希望能给您一点启发！
{% endhint %}

### 3.0 C3-MRO 算法的具体内容

我们先把思想放一放，看看 C3-MRO 算法的具体内容。

> **首先为了方便讨论，我们约定一些符号：**
>
> * 有顺序的元素集合称为 **序列** ，记作$$\[\quad]$$
> * 类 C 的 MRO 亦称为 **C 的线性化**，记作 $$L(C) = \[C\_1,C\_2,\cdots,C\_N]$$
> * 在 $$L(C) = \[C\_1,C\_2,\cdots,C\_N]$$ 中，称首项 $$C\_1$$ 为 $$L(C)$$ 的 **头** ，记作 $$L(C)\_{head}$$
> * 在 $$L(C) = \[C\_1,C\_2,\cdots,C\_N]$$ 中，称除去首项的后续元素序列 $$\[C\_2, \cdots,C\_N]$$ （可以为空）为 $$L(C)$$ 的 **尾** ，记作 $$L(C)\_{tail}$$
> * 在其他序列的尾中不曾出现的头，我们称之为 **好头** ，记作 $$H$$
> * 连接两个序列的操作记作 $$\boldsymbol+$$
>
> **同时，根据 OOP 的通识：**
>
> 记 $$object$$ 为 **根类**（即类继承中最早出现的类，也是所有其他类的超类）：
>
> $$L(object)=\[object]$$

**如果一个 类** $$C$$ **继承自基类** $$B\_1, B\_2, \cdots, B\_N$$ **那么 C3-MRO 算法的公式就是：**

$$
L(C) = \[C] + merge \Big( L(B\_1), L(B\_2), \cdots, L(B\_N), \quad\[B\_1, B\_2, \cdots, B\_N] \Big)
$$

C3-MRO 方法的主式是很清晰明了的，但其中还有一个自定运算 $$merge$$ 待解释。

$$merge$$ **是一个特殊的序列合并操作，接受多个序列输入，输出一个新的序列。**\
以主式为例，其过程为：

1. **首个输入序列** $$L(B\_1)$$，取其 **头** $$L(B\_1)\_{head}$$
2. 检查 **上一步取头序列后面的输入序列的尾中** 是否有与 **上一步取出的头** 相同的元素：如果 **没有** ，说明 $$L(B\_1)*{head}$$ 为 **好头** $$H$$ ，将其提取至外层，然后从所有序列中删除该 **好头** ，回到 步骤 1 继续；如果 **有** ，取 **下一个输入序列的头** $$L(B\_2)*{head}$$ ，从步骤 2 继续。

**重复上述步骤，直至序列为空或者不能再找出好头：**\
如果 **序列为空** ，则算法结束；\
如果 **序列不为空** ，并且无法找出可以输出的元素，那么 Python 会抛出 `TypeError` 异常。

***多说无益，让我们来实际上手：***

{% hint style="warning" %}
**强烈建议您阅读并尝试自行推导此例，这将有助于您理解下文。**
{% endhint %}

{% @mermaid/diagram content="graph BT
Z --> K1
Z --> K3
Z --> K2
K1 --> C
K1 --> A
K1 --> B
K3 --> A
K3 --> D
K2 --> B
K2 --> D
K2 --> E
C --> O
A --> O
B --> O
D --> O
E --> O" %}

```python
# 这里是伪代码表示
O=object
class A(O)
class B(O)
class C(O)
class D(O)
class E(O)
class K1(A, B, C)
class K2(D, B, E)
class K3(D, A)
class Z(K1, K2, K3)
```

{% hint style="info" %}
**不要急，也不要怕，这并不复杂，只是看起来比较长而已，让我们一步一步来。**
{% endhint %}

我们先来试试简单的，从作为根类存在的 `O`（也就是 `object`）开始怎么样：

```bash
L(O)  := [O]
```

好我们稍微提升点难度，来看看 `A` ：

```bash
L(A)  :=  [A] + merge(L(O), [O])  # 先展开主式
       =  [A] + merge([O], [O])   # 接着展开右边的线性化运算 L(O)=O
       =  [A, O]                  # 头 O 不在其他序列的尾中，提出 O
```

找到点感觉了吗？试试自行完成下面几个：

```bash
L(B)  :=  [B, O]
L(C)  :=  [C, O]
L(D)  :=  [D, O]
L(E)  :=  [E, O]
```

有没有觉得上面的计算其实都有点小题大作？\
这主要是因为截至目前都只是 **单继承** ，凭借直观感受就完全足够了。

不过接下来就是这个算法展现魔力的时候了，让我们来看看 **多继承** 的情况：

```bash
# 这里就比较复杂
# 慢慢来，不要急
L(K1)  :=  [K1] + merge(L(A), L(B), L(C), [A, B, C])        # 先展开主式
        =  [K1] + merge([A, O], [B, O], [C, O], [A, B, C])  # 然后展开其中我们已经得出结果的线性化运算
        =  [K1, A] + merge([O], [B, O], [C, O], [B, C])     # 从第一个序列开始：A 是个好头，把它提出来
        =  [K1, A, B] + merge([O], [O], [C, O], [C])        # O 不是个好头啊，没关系，从下一个序列开始，B 是好头，提取出来
        =  [K1, A, B, C] + merge([O], [O], [O])             # C 同上
        =  [K1, A, B, C, O]                                 # 这里就很明显了，都是甚至没有尾能和头比较（都是空尾），提出 O


######### 接下来就是重复这个过程了

L(K2)  :=  [K2] + merge(L(D), L(B), L(E), [D, B, E])
        =  [K2] + merge([D, O], [B, O], [E, O], [D, B, E])
        =  [K2, D] + merge([O], [B, O], [E, O], [B, E])
        =  [K2, D, B] + merge([O], [O], [E, O], [E])
        =  [K2, D, B, E] + merge([O], [O], [O])
        =  [K2, D, B, E, O]

L(K3)  :=  [K3] + merge(L(D), L(A), [D, A])
        =  [K3] + merge([D, O], [A, O], [D, A])
        =  [K3, D] + merge([O], [A, O], [A])
        =  [K3, D, A] + merge([O], [O])
        =  [K3, D, A, O]

L(Z)  :=  [Z] + merge(L(K1), L(K2), L(K3), [K1, K2, K3])
       =  [Z] + merge([K1, A, B, C, O], [K2, D, B, E, O], [K3, D, A, O], [K1, K2, K3])
       =  [Z, K1] + merge([A, B, C, O], [K2, D, B, E, O], [K3, D, A, O], [K2, K3])
       =  [Z, K1, K2] + merge([A, B, C, O], [D, B, E, O], [K3, D, A, O], [K3])
       =  [Z, K1, K2, K3] + merge([A, B, C, O], [D, B, E, O], [D, A, O])
       =  [Z, K1, K2, K3, D] + merge([A, B, C, O], [B, E, O], [A, O])
       =  [Z, K1, K2, K3, D, A] + merge([B, C, O], [B, E, O], [O])
       =  [Z, K1, K2, K3, D, A, B] + merge([C, O], [E, O], [O])
       =  [Z, K1, K2, K3, D, A, B, C] + merge([O], [E, O], [O])
       =  [Z, K1, K2, K3, D, A, B, C, E] + merge([O], [O], [O])
       =  [Z, K1, K2, K3, D, A, B, C, E, O]
```

### 3.1 理解算法核心思想

MRO 本质是 **顺序** ，而用于生成这个顺序的 C3-MRO 算法，本质上也就是个 **排序算法** 。

个人是从 **多属性排序** 的角度来理解 C3-MRO 算法的。\
多属性排序中的核心问题，其实就是 **决定属性间的优先级** 。

**听说过** ***机器人三定律*** **吗？** 如果你是第一次看到它。不妨去了解一下。\
~~作为程序员，这是我们迟早要面对的问题 XD~~

个人认为，我们完全可以将 C3-MRO 算法的核心思想总结为 **MRO 三定律**：

{% hint style="success" %}

> > > **Ⅰ. MRO 应保证子类在父类前。**
> >
> > **Ⅱ. MRO 应维持单调性，但不能因此违反 Ⅰ。**
>
> **Ⅲ. MRO 应遵循局部优先性，但不能因此违反 Ⅰ 或 Ⅱ。**
> {% endhint %}

那么，**MRO 三定律** 是如何体现在具体算法中的呢？

#### **Ⅰ. 子类在父类前**

> **这是继承和多态的基本立足点。**
>
> > 例：子类可以重载父类的属性和方法（这一特性就被称为多态）

这一定律在算法中主要体现在：

**（1）C 本身是自己的子类，所以在算法主式中首先会将 C 抽出来，然后对其父类依序递归调用**

$$
L(C) = {\color{red}\[C]} + merge \Big( L(B\_1), L(B\_2), \cdots, L(B\_N), \quad \[B\_1, B\_2, \cdots, B\_N] \Big)
$$

这个操作微不足道，貌似有点配不上它作为第一定律的最高身份是吗？\
不，恰相反，**大道至简**！

要注意，算法是 **递归** 的，这个**小操作**会在层层递归中一步步构建出整体的**大秩序**。\
我们可以思考一下递归的过程：

递归一次又一次的调用自身后，最后一层会递归在 $$object$$ 返回。\
外面一层递归再取出当前的类（也就是 `object` 的子类），放在最前面。\
外面一层递归再取出当前的类（`object` 的子类的子类），放在最前面。\
外面一层递归再取出当前的类（`object` 的子类的子类的子类），放在最前面。\
$$\cdots\cdots$$\
$$\cdots$$

调用从继承结构树中最下方开始（此时向上），递归返回与调用的顺序相反（第一次反转，此时向下）；\
而每次把当前类放到序列最前面，会构造一个和遍历顺序相反的序列（第二次反转，此时向上）；\
所以最终生成的序列与递归调用的方向相同（反反得正的道理）。

这个小小的操作，实际上让我们完成了 **沿继承结构树一路向上的遍历** 。

（2）$$merge$$ 中寻找好头并提取（不包括在末尾的原生父类序列中的判断）

$$
L(C) = \[C] + {\color{red}merge \Big(L(B\_1), L\[B\_2], \cdots, L\[B\_N],} \quad \[B\_1, B\_2, \cdots, B\_N] \color{red}\Big)
$$

**(1)** 决定了我们的大方向是沿继承结构一路向上，但还存在一个问题，那就是如何在具体继承产生分岔时选择下一步的方向：

{% @mermaid/diagram content="graph BT
C --> A
A --> B
B --> O
A --> O" %}

C -> A 后接下来我们该怎么做呢，C -> A -> B -> O 还是 C-> A -> O -> B？\
很明显，为了保证子类 B 在其父类 O 的前面，我们的决策应该是 C -> A -> B -> O。\
作为当年~~黑魔法大战~~的胜者，C3-MRO 算法自然也能做出同样聪明的决策。\
我们是通过图形的直观观察判断的，那么算法是如何做到的呢？

我们来看看具体推导：

$$
O\ 作为头出现在其他序列（不包含最后的原生父类序列）的尾中\ \Updownarrow \\\ O\ 仍是其余未被继承（已继承的都被提取到外面了）的类的父类
$$

以上两行本质是相同的，所以 $$merge$$ 中通过 **在不包含最后的原生父类序列中找好头** 的操作完成了 **在继承结构分岔处的抉择。**~~其实个人倾向于把这个操作命名为 ***认亲*** XD~~

#### **Ⅱ. 单调性**

> **一个类的 MRO 被保持并包含在其任何子类的 MRO 中。**
>
> > 例：$$C$$ 的 MRO 中存在 $$B\_1$$ 和 $$B\_2$$，且 $$B\_1$$ 在 $$B\_2$$ 之前，则在 $$C$$ 的任何子类的 MRO 中，也存在 $$B\_1$$ 和 $$B\_2$$，且 $$B\_1$$ 在 $$B\_2$$ 之前。

单调性保证了最基础的 MRO 的 **稳定性**，**不会因查询起点不同而变动**。\
事实上，C3-MRO 算法最终能够脱颖而出，主要原因就是在 Python 2.3 版本最初部分候选的 ~~黑魔法~~ 中，只有它表现出了良好的单调性。\
其余的~~黑魔法~~虽然能应对绝大多数的多继承问题，但在特定情况下并不能维持单调性。

这一定律在算法中主要体现在：**算法主式的等式形式及其递归遍历的逻辑。**

$$
{\color{red}L(}C{\color{red}) =}\ \[C] + merge \Big({\color{red}L(}B\_1{\color{red})}, {\color{red}L(}B\_2{\color{red})}, \cdots, {\color{red}L(}B\_N{\color{red})}, \quad \[B\_1, B\_2, \cdots, B\_N] \Big)
$$

```
 L(C)  :=  [C] + merge(L(A), L(B), [A, B])
        =  [C] + merge([A, O], [B, O], [A, B])
        =  [C, A] + merge([O], [B, O], [B])      # 我们发现 O 不是好头，所以跳过了它
        =  [C, A, B] + merge([O], [O],) 
        =  [C, A, B, O]
```

事实上，这 **类似于数学归纳法**，任何后一轮的计算都是建立在前一轮计算的结果基础上的，自然能保持单调性。\
当然，$$merge$$ 中具体操作也很重要，但实在是难以形象说明，所以就不在此陈述。

#### **Ⅲ. 局部优先性**

> **在继承序列内越靠前的基类，优先级越高。**
>
> > 例：`class C(A, B)` 含有的语义：建立类型 $$C$$ ，首先继承 $$A$$ ，其次继承 $$B$$。

这是 Python 多继承的基本语法设计，是为了 **保证程序员对继承的控制权**。\
无论是什么语言，保证使用者充分的控制权都是必要的。

这一定律在算法中主要体现在：$$merge$$ **中最后的原生父类序列。**

$$
L(C) = \[C] + merge \Big(L(B\_1), L(B\_2), \cdots, L(B\_N), \quad {\color{red}\[B\_1, B\_2, \cdots, B\_N]} \Big)
$$

**实际上** $$merge$$ **最后的原生父类序列仅在部分情况下才会发挥作用。**\
不信的话你可以回看 3.0 一节末尾的例子，在实际推导的过程中除去 $$merge$$ 末尾的原生父类序列，最终你会发现结果并未受到影响。

那么什么时候它才会发挥作用呢？我们来看个特殊例子：

{% @mermaid/diagram content="graph BT
B --> O
B --> A
A --> O
" fullWidth="false" %}

```
 L(B)  :=  [B] + merge(L(O), L(A), [O,A])  
        =  [B] + merge([O], [A,O], [O,A])
           # 这里我们首先取 O 为头，但很明显它出现在了第二个序列的尾中，不是好头
           # 我们从第二个序列的头 A 继续，但我们发现，也不是好头
           # 再取第三个序列的头 O ，很遗憾，它也不是。最终，无好头，引发 TypeError
```

这里突然跳出来的 `TypeError` 是 **Python 设计者们的苦心**，目的是阻止开发者创建这种在 OOP 概念上逻辑混乱的继承体系，从根源上解决多继承的问题。

但在这里我们不谈 OOP 概念的相关问题，单就针对“MRO 三定律”来说说理由：

1. 首先，处于局部优先性的考虑，我们应该选择 B -> O -> A，但这就 **违反了`第Ⅰ定律`**。
2. 好吧，那我们索性不要管`第Ⅲ定律`了，走 B -> A -> O 得了。\
   然而在一些复杂结构中 **（鉴于篇幅，在此不做展示，其本质是程序员无法有效控制继承优先级造成的）** 又会出现 **单调性被打破**，**`第Ⅱ定律`被违反** 的情况。

{% hint style="danger" %}
**在 1 中，最重要的`第Ⅰ定律`被破坏；在 2 中，`第Ⅱ定律`与`第Ⅲ定律`同时被破坏。**
{% endhint %}

事实上呢，与 ***机器人三定律*** 一样的是，***MRO 三定律*** 会在某型情况下 **产生定律间的对抗。**

尽管我们已经给定律间设计了优先级来应对，但出现对抗绝对会是一个 **坏情况**，因为它必然 **至少违反其中某个定律**。\
在我们刚才 `TypeError` 的情况中，三条定律都受到了威胁，所以我们要避免这种情况发生。\
Python 语言的设计者们考虑到这一点，就干脆抛出 `TypeError`，阻止开发者创造含糊混乱的继承结构。

{% hint style="success" %}
**不得不说，即便是在近 20 年后的今天回望，这个算法仍是优雅而高效的。**
{% endhint %}

{% hint style="warning" %}
请注意：思想与算法本质上是一体两面，彻底的解耦是不现实的，故作者在这里只挑选了其中易理解的部分进行说，更多的内容留待您自行感悟。
{% endhint %}

### 3.2 用代码完成算法

{% hint style="info" %}

> Talk is cheap. Show me the code.
>
> 废话少说，放码过来。
> {% endhint %}

作者根据个人的理解撰写了 C3-MRO 的 Python 代码实现，**具体说明内容请见注释。**\
\&#xNAN;*Wikipedia 上的内容同为作者编辑更新*

```python
def c3_mro(cls):
    if cls is object:
        # 讨论假设顶层基类为 object，递归终止
        return [object]

    # 构造 C3-MRO 算法的总式，递归开始
    merge_list = [c3_mro(base_cls) for base_cls in cls.__bases__]
    merge_list.append(list(cls.__bases__))
    mro = [cls] + merge(merge_list)
    return mro


def merge(in_lists):
    if not in_lists:
        # 若合并的内容为空，返回空 list
        # 配合下文的排除空 list 操作，递归终止
        return []

    # 遍历要合并的 MRO
    for mro_list in in_lists:
        # 取头
        head = mro_list[0]
        # 遍历要合并的 MRO（与外一层相同），检查尾中是否有头
        for cmp_list in in_lists:
            if cmp_list is mro_list:
                continue

            if head in cmp_list[1:]:
                break
        else:
            # 筛选出好头
            next_list = []
            for merge_item in in_lists:
                if head in merge_item:
                    merge_item.remove(head)

                if merge_item:
                    # 排除空 list
                    next_list.append(merge_item)
            # 递归开始
            return [head] + merge(next_list)
    else:
        # 无好头，引发类型错误
        raise TypeError
```

### 3.3 留待思考与评论的问题

下面我将给出两个 **开放性问题** ，如果您感兴趣的话可以在评论区留下您对这两个问题的看法。q(≧▽≦q)

#### ~~魔鬼~~三角继承问题

{% @mermaid/diagram content="graph BT
B --> A
B --> O
A --> O" %}

> 有一个基类 `O`，定义了方法 `f`，`A` 类继承了 `O` 类，`B` 类继承了 `O` 类和 `A` 类。\
> 那么出现一个问题，`B` 类的 `f` 方法该如何调用？

~~**恐怖**~~**菱形继承问题：**

> 有一个基类 `O` ，定义了方法 `f` ，`A` 类和 `B` 类继承了 `O` 类，`C` 类继承了 `A` 和 `B` 类。\
> 那么出现一个问题，`C` 类的 `f` 方法应该如何调用？

{% @mermaid/diagram content="graph BT
C --> A
C --> B
A --> O
B --> O" %}

在 Python3 普及的今天，这都是再正常不过的操作。\
（把 `O` 看作 `object` ，Python 3 所有类默认继承自 `object` ）\
但在使用 Python 2.2 `典型类` 的 21 世纪初，这两个问题不知道让多少开发者 *聪明绝顶* XD！\
部分人因而生惧，冠以魔鬼和恐怖之名。

**当然，C3-MRO 已经很好地解决了这两个问题。**\
**但如果剥离具体语言实现的情境，纯粹以面向对象设计的视角来看待，这两个问题的回答完全是开放性的。**

{% hint style="success" %}
讨论与交流是知识传播的必要途径，不妨在评论区留下您对这两个问题的看法。 (～￣▽￣)～
{% endhint %}

## 4. 参考源

1. [The Python 2.3 Method Resolution Order](https://www.python.org/download/releases/2.3/mro/)
2. [The paper A Monotonic Superclass Linearization for Dylan](https://doi.org/10.1145/236337.236343)
3. [C3 线性化算法与 MRO——理解 Python 中的多继承](http://kaiyuan.me/2016/04/27/C3_linearization/)
4. [C3 linearization](https://en.wikipedia.org/wiki/C3_linearization)
5. [The thread on python-dev started by Samuele Pedroni](https://mail.python.org/pipermail/python-dev/2002-October/029035.html)
6. [PEP 253 -- Subtyping Built-in Types](https://www.python.org/dev/peps/pep-0253/)
7. [Python 方法解析顺序 MRO-C3 算法](https://xubiubiu.com/2019/06/10/python-%E6%96%B9%E6%B3%95%E8%A7%A3%E6%9E%90%E9%A1%BA%E5%BA%8Fmro-c3%E7%AE%97%E6%B3%95/)


# 描述器学习指南

从面向过程到面向对象

## 引言

Python 语言当前使用的解释器主要是 CPython，也就是说，基于面向过程的 C 语言构建了面向对象的 Python，那么其中的基础原理有哪些值得我们学习呢？

{% hint style="success" %}
**描述器**
{% endhint %}

我们来看看官方文档是怎么形容描述器的吧。

> **学习描述器能更深地理解 Python 工作的原理并更加体会到其设计的优雅性。**\
> **描述器是一个强大而通用的协议。**\
> **描述器是特征属性、方法静态方法、类方法和 `super()` 背后的实现机制。**\
> **描述器在 Python 内部被广泛使用，实现了自 2.2 版本中（最早由** [**PEP252**](https://www.python.org/dev/peps/pep-0252/) **提出）引入的新式类。**\
> **描述器简化了底层的 C 代码并为 Python 的日常程序提供了一组灵活的新工具。**

事实上描述器这个主题并不冷门，网上已有了大量的讨论。但是前几天在翻译官方文档间隙查资料的时候，发现已有的博文和参考资料大都比较零散，故在此作以简单整合。

{% hint style="info" %}
**本文的编排顺序是作者精心调整过的，建议您按照标题顺序依次阅读。**
{% endhint %}

作者秉持 **KISS** 主义，故而本文不对已有的博文做重复陈述，只给出对应链接。

**Keep it Simple, Stupid!**

## 0. 粗览官方文档

首先我们当然要 **浏览** 一下官方文档了，作者已经贡献了简中翻译。

[【官方文档】描述器使用指南](https://docs.python.org/zh-cn/3.9/howto/descriptor.html)

![transifex](/files/-MeXv_RROPI-pXMHAEBI)

## 1. 了解 Python 属性访问顺序

首先，面向对象与面向过程的区别之一就是`cls.attribute`形式的调用，这被称为属性调用，这里的属性是指广义上的，**包括基础属性和方法**。\
那么我们就先来了解一下 Python 中的属性调用的顺序：

[python 高级编程——描述符 Descriptor 详解（上篇）——python 对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84848341)\
[python 高级编程——描述符 Descriptor 详解（中篇）——python 对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84767061)

### **对象属性访问顺序**

1. 依照 **MRO** 顺序的类的类属性中的 **数据描述器属性**
2. **实例对象的属性**`object.__dict__`
3. 依照 MRO 顺序的类的类属性中的 **非数据描述器属性**
4. 依照 MRO 顺序的类的类属性中的 **普通（非描述器）属性**`cls.__dict__`

### **类属性访问顺序**

1. 依照元类的 MRO 顺序的类的类属性中的 **元类数据描述器属性**
2. 依照 MRO 顺序的类的类属性中的 **数据描述器属性**
3. 依照 MRO 顺序的类的类属性中的 **普通（非描述器）属性**`cls.__dict__`
4. 依照 MRO 顺序的类的类属性中的 **非数据描述器属性**
5. 依照元类的 MRO 顺序的类的类属性中的 **元类非数据描述器属性**

{% hint style="info" %}
Python 中 **类的本质是元类创建的对象**，所以相当于是外面套了一层不包含普通属性（亦即非描述器属性）的对象属性访问顺序。
{% endhint %}

## 2. 了解描述器协议

现在我们可以去看一下描述器的核心内容了。

[python 高级编程——描述符 Descriptor 详解（下篇）——python 描述符三剑客详解](https://blog.csdn.net/qq_27825451/article/details/84848341)

### **描述器协议**

```python
descr.__get__(self, obj, type=None)

descr.__set__(self, obj, value)

descr.__delete__(self, obj)
```

定义这些方法中的任何一个的对象被视为描述器，在被作为属性时覆盖其默认行为。

> 仅当一个包含这些方法的类（称为 *描述器类*）的实例出现于一个 *所有者类* 中的时候才会起作用（该描述器必须在所有者类或其某个上级类的字典中）。

如果一个对象定义了 `__set__()` 或 `__delete__()`，则它会被视为数据描述器。\
仅定义了 `__get__()` 的描述器称为非数据描述器（它们通常被用于方法，但也可以有其他用途）。

数据和非数据描述器的不同之处在于，如何计算实例字典中条目的替代值。\
如果实例的字典具有与数据描述器同名的条目，则数据描述器优先。如果实例的字典具有与非数据描述器同名的条目，则该字典条目优先。

为了使数据描述器成为只读的，应该同时定义 `__get__()` 和 `__set__()` ，并在 `__set__()` 中引发 `AttributeError` 。用引发异常的占位符定义 `__set__()` 方法使其成为数据描述器。

## 3. 探究描述器核心原理

如果想要彻底地理解描述器，那么我们就不得不了解一下描述器的具体代码实现。\
但是直接上源码未必太过硬核，以流程图的形式去解析可能是最好的方式，下面这篇文章正是如此。

[描述器 (1)](https://www.dazhuanlan.com/2020/02/29/5e5965cea4d60/)

## 4. 实例练习

学习了这么多原理，最后自然要来个有实际意义例子来练练手了。看看怎样利用描述器来实现装饰器 `property` 吧。

[property 装饰器的描述器实现](/python/property)

## 5. 细究官方文档

最后我们就可以再回头看看官方文档了，相信这次你可以轻松理解其中内容。

[【官方文档】描述器使用指南](https://docs.python.org/zh-cn/3.9/howto/descriptor.html)

## 参考源

1. [【官方文档】描述器使用指南](https://docs.python.org/zh-cn/3.9/howto/descriptor.html)
2. [python 高级编程——描述符 Descriptor 详解（上篇）——python 对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84848341)
3. [python 高级编程——描述符 Descriptor 详解（中篇）——python 对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84767061)
4. [python 高级编程——描述符 Descriptor 详解（下篇）——python 描述符三剑客详解](https://blog.csdn.net/qq_27825451/article/details/84848341)
5. [python 高级编程——描述符 Descriptor 详解（补充篇）——python 描述符实现一些底层高级功能](https://blog.csdn.net/qq_27825451/article/details/84848341)
6. [描述器 (1)](https://www.dazhuanlan.com/2020/02/29/5e5965cea4d60/)
7. [Python 中的类与描述器 (Descriptors)](https://blog.csdn.net/u013008795/article/details/90646667)
8. [property 装饰器的描述器实现](https://blog.csdn.net/WH2099/article/details/105328929)


# 描述器实现 property

描述器实战应用

## 引言

在 Python 官方文档中的 [描述器使用指南](https://docs.python.org/zh-cn/3.9/howto/descriptor.html) 一篇中，给出了常用装饰器 `property` 的 Python 代码模拟实现，且这个实现是基于描述器原理的。在本文中，作者将利用这段代码，向你展示 **描述器的实际运行原理**。

## 装饰器基本内容

首先我们回忆一下装饰器的有关内容。

> **装饰器本质是个返回函数的函数，表现为数学概念中的复合函数**$$\big(g \circ f\big)(x) \Rightarrow g\big(f(x)\big)$$

下面我们用伪代码再补充一些容易产生疑问的情况。

### **多层装饰器的含义**

```python
@dec2
@dec1
def func(arg1, arg2, ...):
    pass
```

↑↑↑ 等价于 ↓↓↓

```python
func = dec2(dec1(func))
```

### **带参装饰器的含义**

```python
@decomaker(argA, argB, ...)
def func(arg1, arg2, ...):
    pass
```

↑↑↑ 等价于 ↓↓↓

```python
func = decomaker(argA, argB, ...)(func)
```

类装饰器和函数装饰器是一致的，只相当于将 func 代表的函数换做 cls 代表的类罢了，故这里不再多做涉及。

如果对于装饰器还有问题的话建议阅读一下官方 PEP，可以直接使用 Google 翻译成中文，可读性还是可以接受的。

[PEP 318 -- Decorators for Functions and Methods](https://www.python.org/dev/peps/pep-0318/) [PEP 3129 – Class Decorators](https://www.python.org/dev/peps/pep-3129/)

## 描述器基本内容

这里推荐我针对描述器撰写的上一篇博文

[描述器学习指南](/python/descriptor)

## 官方模拟的源码

我们首先看一下用描述器模拟实现装饰器 `property` 的源代码。

*（这里大概看一下就好，我们后文再详细分析）*

```python
class Property:
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)
```

## 代码分析

### 改写测试用代码

其实作者比较喜欢的方式是利用 VS Code 在代码段顶部就加上断点，然后逐句执行查看代码的具体运行位置和变量值。\
但这种方式难以通过文字向大家展示，所以我换了个变通的方式，在每个关键环节都加一个 `print()` 输出相关内容，这样我们看代码的命令行反馈就可以了。

更改后的测试代码如下：

```python
class Property(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    print('body of Property')

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        print(f'Property.__init__() {self=}')
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        print(f'Property.__get__() {self=} {obj=} {objtype=}')
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        print(f'Property.__set__() {self=} {obj=}')
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        print(f'Property.__delete__() {self=} {obj=}')
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        print(f'Property.getter() {self=}')
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        print(f'Property.setter() {self=}')
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        print(f'Property.deleter() {self=}')
        return type(self)(self.fget, self.fset, fdel, self.__doc__)


class A(object):

    print('body of A')

    def __init__(self):
        print(f'A.__init__() {self=}')
        self._x=0
        pass 

    @Property       # 事实上这里就是 getter 哦
    def x(self):
        print(f'A.x.fget() {self=}')
        return self._x

    @x.setter
    def x(self, value):
        print(f'A.x.fset() {self=}')
        self._x=value
    @x.deleter
    def x(self):
        print(f'A.x.fdelete() {self=}')
        del self._x

    # setter 和 deleter 的函数命名并不会有具体含义，所以按照官方的示例，直接与 getter 同名即可

print('\n----- before a1 = A() -----')
a1 = A()
print('\n----- before   a1.x   -----')
a1.x
print('\n-----before  a1.x = 1 -----')
a1.x = 1
print('\n-----before del a1.x  -----')
del a1.x

print()

print('\n----- before a2 = A() -----')
a2 = A()
print('\n----- before   a2.x   -----')
a2.x
print('\n-----before  a2.x = 1 -----')
a2.x = 1
print('\n-----before del a2.x  -----')
del a2.x
```

### 全部输出

运行以上代码得到的输出是：

```
body of Property
body of A
Property.__init__() self=<__main__.Property object at 0x000002A7BBA310A0>
Property.setter() self=<__main__.Property object at 0x000002A7BBA310A0>
Property.__init__() self=<__main__.Property object at 0x000002A7BBA31100>
Property.deleter() self=<__main__.Property object at 0x000002A7BBA31100>
Property.__init__() self=<__main__.Property object at 0x000002A7BBA310A0>

----- before a1 = A() -----
A.__init__() self=<__main__.A object at 0x000002A7BBA31100>

----- before   a1.x   -----
Property.__get__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100> objtype=<class '__main__.A'>
A.x.fget() self=<__main__.A object at 0x000002A7BBA31100>

-----before  a1.x = 1 -----
Property.__set__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100>
A.x.fset() self=<__main__.A object at 0x000002A7BBA31100>

-----before del a1.x  -----
Property.__delete__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100>
A.x.fdelete() self=<__main__.A object at 0x000002A7BBA31100>


----- before a2 = A() -----
A.__init__() self=<__main__.A object at 0x000002A7BBA31160>

----- before   a2.x   -----
Property.__get__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160> objtype=<class '__main__.A'>
A.x.fget() self=<__main__.A object at 0x000002A7BBA31160>

-----before  a2.x = 1 -----
Property.__set__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160>
A.x.fset() self=<__main__.A object at 0x000002A7BBA31160>

-----before del a2.x  -----
Property.__delete__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160>
A.x.fdelete() self=<__main__.A object at 0x000002A7BBA31160>
```

**由于这其中涉及的内容较多，我们拆开来做分析。**

### 初始化部分

```
body of Property        # Python 解释器在发现类创建操作后，对类进行初始化
body of A               # 类初始化首先执行的就是类体中的代码，而类体中的 @Property def x(self): .... 相当于被转化为了 x=Property(x)  注意后面这个 x 是原本的函数
                        # 如果不理解的话建议回头看一下最上面的 装饰器基本内容
Property.__init__() self=<__main__.Property object at 0x000002A7BBA310A0>        # 继而 Property 对象初始化
Property.setter() self=<__main__.Property object at 0x000002A7BBA310A0>          # 这里对应的是 @x.setter
Property.__init__() self=<__main__.Property object at 0x000002A7BBA31100>        # 注意这里是在原本 Property 的对象基础上，又创造了一个新的Property对象（具体参见Property的setter方法）
Property.deleter() self=<__main__.Property object at 0x000002A7BBA31100>         # 对应 @x.deleter
Property.__init__() self=<__main__.Property object at 0x000002A7BBA310A0>        # 和前面的 setter 一样，这里也是返回了新的 Property 对象
                                                                                 # 自这之后， A 类中和 x 挂勾的 Property 就确定下来了
```

### 对象 a1 创建及属性操作部分

```
----- before a1 = A() -----
A.__init__() self=<__main__.A object at 0x000002A7BBA31100>        # a1 实例对象创建的初始化

----- before   a1.x   -----
Property.__get__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100> objtype=<class '__main__.A'>
  # 上面这行是实例对象 a1 想要获取属性 x 的值，Property 作为一个描述器，它的 __get__ 方法被调用
A.x.fget() self=<__main__.A object at 0x000002A7BBA31100>        # 在 Property 的 __get__ 方法中，转调用了 通过 @Property 设置的方法

## setter 和 deleter 的调用方式和 getter 一样，没有本质差别

-----before  a1.x = 1 -----
Property.__set__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100>
A.x.fset() self=<__main__.A object at 0x000002A7BBA31100>

-----before del a1.x  -----
Property.__delete__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31100>
A.x.fdelete() self=<__main__.A object at 0x000002A7BBA31100>
```

### 对象 a2 创建及属性操作部分

```
----- before a2 = A() -----
A.__init__() self=<__main__.A object at 0x000002A7BBA31160>        # a2 实例对象初始化，a2 和 a1 不是相同的对象

                            # 以下的调用整体上与前面 a1 的调用方式是一样的
                            # 但是请注意：尽管 a2 和 a1 不是相同的对象，但 Property 对象还是同一个
                            # 这说明类对应的描述器对象其实是唯一的
----- before   a2.x   -----
Property.__get__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160> objtype=<class '__main__.A'>
A.x.fget() self=<__main__.A object at 0x000002A7BBA31160>

-----before  a2.x = 1 -----
Property.__set__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160>
A.x.fset() self=<__main__.A object at 0x000002A7BBA31160>

-----before del a2.x  -----
Property.__delete__() self=<__main__.Property object at 0x000002A7BBA310A0> obj=<__main__.A object at 0x000002A7BBA31160>
A.x.fdelete() self=<__main__.A object at 0x000002A7BBA31160>
```

## @property 中的小陷阱

{% hint style="danger" %}
**@property 装饰后生成的描述器实际上成为了数据描述器！**
{% endhint %}

## 扩展内容

其实在同一篇中官方也给出了 `staticmethod` 和 `classmethod` 的类似模拟实现，有兴趣的读者也不妨一览：

```python
class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f

class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, klass=None):
        if klass is None:
            klass = type(obj)
        def newfunc(*args):
            return self.f(klass, *args)
        return newfunc
```

## 参考

1. [描述器使用指南](https://docs.python.org/zh-cn/3.9/howto/descriptor.html)
2. [property 装饰器的描述器实现](/python/property)
3. [PEP 318 -- Decorators for Functions and Methods](https://www.python.org/dev/peps/pep-0318/)
4. [PEP 3129 – Class Decorators](https://www.python.org/dev/peps/pep-3129/)


# 如何做一个好中介

yield from 委派生成器语句解析

## 0. 声明

{% hint style="warning" %}
**不从 `0` 开始难不成从 `1` 开始？你知道吗，世上只有 `10` 种人，程序员和非程序员;**
{% endhint %}

{% hint style="info" %}
本文假设您已经掌握 **生成器（Generators）** 相关的知识
{% endhint %}

## 1. 基础回顾

### 1.0 生成器（Generators） `yield`

{% hint style="info" %}
Python 生成器本质是一种 **迭代器** ，但功能更强大。
{% endhint %}

在 Python 2.2 版本（2001 年）中，经由 [PEP 255](https://www.python.org/dev/peps/pep-0255/) 引入了 **生成器** 的概念。其最初是为了解决开发者经常遇到的一个小问题：

> 当生产者函数完成一项艰苦的工作以至于 **需要维持所生成的值之间的状态** 时，大多数编程语言都无法提供一种愉悦而有效的解决方案，只能将回调函数添加到生产者的参数列表中，以对每个生成的值进行调用。

自此以后，Python 的关键字大家庭里又多了一员 **`yield`** 。而生成器这个概念，也伴随着 Python 走过了 20 年 的风风雨雨，至今，它已经是 Python 中不可分离的重要特性。

{% hint style="warning" %}
探讨生成器的重要性及其延伸开来的广阔特性（如基于生成器的协程）足以另起一篇万字长文，故在此不多做涉猎，但可以肯定的是：

**不用生成器，何谈 Pythonic？**
{% endhint %}

### 1.1 委派生成器 `yield from`

*在 Python 3.3 版本（2011 年）中，经由 PEP 380 引入了这个新的语法，其目的主要是为了解决伴随着生成器在 Python 中的大量使用而出现的生成器间组合的需求。*

首先我们来看一看各种官方资料中有关这一委派的说明好了：

> * **供生成器将其部分操作委托给另一生成器。这允许包含 `yield` 的一段代码被分解并放置在另一个生成器中。此外，允许子生成器返回一个值，并且该值可用于委派生成器。**
> * 当使用 `yield from <expr>` 时，所提供的表达式必须是一个 **可迭代对象** 。**迭代该可迭代对象所产生的值会被直接传递给当前生成器方法的调用者**。任何通过 [`send()`](https://docs.python.org/zh-cn/3/reference/expressions.html#generator.send) 传入的值以及任何通过 [`throw()`](https://docs.python.org/zh-cn/3/reference/expressions.html#generator.throw) 传入的异常 **如果有适当的方法则会被传给下层迭代器** 。如果不是这种情况，那么 [`send()`](https://docs.python.org/zh-cn/3/reference/expressions.html#generator.send) 将引发 [`AttributeError`](https://docs.python.org/zh-cn/3/library/exceptions.html#AttributeError) 或 [`TypeError`](https://docs.python.org/zh-cn/3/library/exceptions.html#TypeError)，而 [`throw()`](https://docs.python.org/zh-cn/3/reference/expressions.html#generator.throw) 将立即引发所转入的异常。

感觉不说人话啊有莫有。。。。。。没事不要急，咱们先把这死板的概念放一边，来看看这玩意都有什么用：

* 这个语法的提出促进了 **基于生成器的协程** 的发展，如今所使用的协程关键字 `async` `await` 以及标准库中的 `asyncio` 就是最好的例子。如果你也曾为这些复杂的概念头疼过 XD，那你必然在回溯报错的过程中多多少少见到了底层一个又一个的 `yield from` 。

{% hint style="info" %}
协程相关内容超出本文讨论范围，在这里不作展开。
{% endhint %}

还是不懂？那我们用代码来说话：

```python
def no_yield_from_generator():
    iterable = (0, 1, 2, 3)
    for i in iteralbe:
        yield i

def yield_from_generator():
    iterable = (0, 1, 2, 3)
    yield from iterable
```

简单直白，一眼就能懂意思是吧？`yield from` 就是可以让我们少写一层 `for` ？

不要急，这只是它最简单的作用罢了。**你有没有想过，如果这个 `iterable` 本身也是个生成器，那么外面一层生成器的 `send()`** **`throw()`** **`close()` 被调用后要怎么办？**

{% hint style="success" %}
**委派生成器 `yield from` 最重要的作用是当一个 中介，协调两个嵌套的生成器的工作** 。
{% endhint %}

咱当时理解到这里的时候，心生疑惑了：不就是个委托调用吗？能有多难，咱自己做不行吗？

咱现在可以明确的说，还真的挺难的，原因且听咱细细道来。

生成器用着方便，但其底层的实现还是相对复杂的。更不幸的是，在基于生成器的协程发展的过程中，为生成器引入了 `send()` `throw()` `close()` 等新方法，这让委托调用变得复杂化\_（中介哪有那么好当 ╮(╯▽╰)╭）\_。\
尽管可以自己来手工实现一些简单的，但随着条件的复杂化和调用的多样化，这些仅关注于部分内容的处理都会变成埋下的 **雷** 。\
\&#xNAN;*相信我，你不会想亲自体验一次的 ╰(艹皿艹 )！*\
所以这种 ***黑魔法研究*** 的任务还是交给官方开发组来做吧。

~~yield from 中介所，多个中间商赚差价，让你的代码更好看！~~

## 2. 原理解析

### 2.0 完整语义

首先，既然 `yield from` 涉及了两个生成器，为了便于后文叙述，我们需要先区分它们。以代码为例：

```python
def generator():
    for i in range(9):
        yield i

def delegated_generator():
    yield from generator()    
    
```

外层的生成器 **`delegated_generator()` 称作 委派生成器**，内层的这个 **`generator()` 就简单称之为 迭代器** 就好。

{% hint style="info" %}
**生成器本质上是一种特殊的迭代器。**
{% endhint %}

`yield from` 的具体语义如下：

* 作为一个中介，首先 **迭代器产生的任何值都将直接传递给调用方** 。
* **使用** **`send()` 发送给委派生成器的任何值都将直接传递给迭代器：**
  * 如果发送的值为 `None`，则调用迭代器的 `__next__()` 方法。
  * 如果发送的值不为 `None`，则调用迭代器的 `send()` 方法。如果调用引发 `StopIteration` 则恢复委派生成器的执行。任何其他异常都会传播到委派生成器。
* \*\*抛出到委派生成器中的 `GeneratorExit` 以外的异常被传递给迭代器的 `throw()` 方法。\*\*如果调用引发 `StopIteration`，则恢复委派生成器的执行。任何其他异常都会传播到委派生成器。
* \*\*如果在委派生成器中抛出 `GeneratorExit` 异常，或者委派生成器的 `close()` 方法被调用，则尝试调用（如果有则调用）迭代器的 `close()` 方法如果。\*\*如果此调用导致异常，则将其传播到委派生成器。否则，在委派生成器中引发 `GeneratorExit`。
* `yield from` **表达式的值** 是迭代器终止时引发的\*\*`StopIteration` 异常的第一个参数\*\*。
* 在生成器中，**`return expr`** 会导致在退出生成器时引发 **`StopIteration(expr)`** 。

### 2.1 代码示范

```python
RESULT = yield from EXPR
```

**↑↑↑↑↑↑ 上面这个语句，实际就相当于 ↓↓↓↓↓↓**

```python
iterator = iter(EXPR)
try:
    yield_value = next(iterator)
except StopIteration as exception:
    result_value = exception.value
else:
    while 1:
        try:
            send_value = yield yield_value
        except GeneratorExit as generator_exit:
            try:
                close_method = iterator.close
            except AttributeError:
                pass
            else:
                close_method()
            raise generator_exit
        except BaseException as base_exception:
            exception_info = sys.exc_info()
            try:
                throw_method = iterator.throw
            except AttributeError:
                raise base_exception
            else:
                try:
                    yield_value = throw_method(*exception_info)
                except StopIteration as stop_iteration:
                    result_value = stop_iteration.value
                    break
        else:
            try:
                if send_value is None:
                    yield_value = next(iterator)
                else:
                    yield_value = iterator.send(send_value)
            except StopIteration as stop_iteration:
                result_value = stop_iteration.value
                break
RESULT = result_value
```

## 3. 参考源

[PEP 255 -- Simple Generators](https://www.python.org/dev/peps/pep-0255/)

[PEP 342 -- Coroutines via Enhanced Generators](https://www.python.org/dev/peps/pep-0342/)

[PEP 380 -- Syntax for Delegating to a Subgenerator](https://www.python.org/dev/peps/pep-0380/)


# PEP 阅读清单

Python Enhancement Proposals

{% hint style="success" %}
[**https://www.python.org/dev/peps/**](https://www.python.org/dev/peps/)
{% endhint %}

{% hint style="info" %}
**只是一份简单的清单，只看右侧目录即可获得所有信息。**
{% endhint %}

## PEP 0 -- IndePEPx of Python Enhancement Proposals (PEPs)

### Python 增强建议（PEP）的索引

### PEP 索引

### 【浏览】

## PEP 1 -- PEP Purpose and Guidelines

### PEP 目的和指南

### 内容简述

### 【浏览】

## PEP 8 -- Style Guide for Python Code

### Python 代码样式指南

### 代码样式

### 【理解】：美观简洁，可阅读性

## PEP 20 -- The Zen of Python

### Python 之禅

### `import this`

### 【浏览】

## PEP 230 -- Warning Framework

### 警告框架

### `warning.warn(message [，category [，stacklevel]])` `warnings.filterwarnings(message, category, module, lineno, action)`

### 【理解】：多用 `DeprecationWarning` 提醒用户过期的内容

## PEP 249 -- Python Database API Specification v2.0

### Python 数据库 API 规范 v2.0

### 数据库 API 2.0

### 【浏览】

## PEP 255 -- Simple Generators

### 简单生成器

### 生成器的来源

### 【理解】：世纪大突破啊！

## PEP 318 -- Decorators for Functions and Methods

### 函数和方法的装饰器

### 函数前 `@`

### 【理解】：装饰器就是个返回函数的函数

## PEP 328 – Imports: Multi-Line and Absolute/Relative

### 导入：多行和绝对/相对形式

### `from .a import b`

### 【理解】：`from ... import` 默认为相对导入，`import` 默认为绝对导入

## PEP 342 -- Coroutines via Enhanced Generators

### 基于拓展生成器的协程

### `send()` `throw()` `close()`

### 【理解】：`yield` 由语句变为表达式，生成器扩展了新方法

## PEP 343 -- The "with" Statement

### “with”声明

### `with` `@contextmanager`

### 【理解】：`@contextmmanager` 装饰的函数中包围 yield 的 try 仍线性执行

## PEP 380 -- Syntax for Delegating to a Subgenerator

### 委派子生成器的语法

### `yield from`

### 【理解】：`yield from` 生成的链中异常的处理（可以 throw 到底层）

## PEP 479 -- Change StopIteration handling inside generators

### 更改生成器内部的 `StopIteration` 处理

### 生成器中主动抛出的 `StopIteration` 被包装为 `RuntimeError`

### 【理解】：防止 yield 链的隐式意外中断

## PEP 483 -- The Theory of Type Hints

类型提示的理论

### `typing`

### 【浏览】：就是你把鬼子（静态类型标注）引进村的吗？

## PEP 484 -- Type Hints

### 类型提示

### `typing`

### 【浏览】：终究还是躲不开类型

## PEP 487 -- Simpler customisation of class creation

### 简化类创建的自定义

### `__set_name__` `__init_subclass__`

### 【理解】：`__new__` 中先后增添 `__set_name__` `__init_subclass__`

## PEP 492 -- Coroutines with async and await syntax

### 具有异步和等待语法的协程

### `async` `await`

### 【浏览】

## PEP 508 -- Dependency specification for Python Software Packages

### Python 软件包依赖关系规范

### 内容简述

### 【待阅】

## PEP 514 -- Python registration in the Windows registry

### Windows 注册表中的 Python 注册

### 内容简述

### 【待阅】

## PEP 520 -- Preserving Class Attribute Definition Order

### 保留类属性的定义顺序

### `__definition_order__`

### 【理解】：3.6 中 compact dict 已经替代了 **definition\_order**，字典默认保留插入顺序

## PEP 525 -- Asynchronous Generators

### 异步生成器

### 内容简述

### 【浏览】

## PEP 526 -- Syntax for Variable Annotations

### 变量标注的语法

### `:`

### 【理解】：PEP 484 基础上的变量标注

## PEP 544 -- Protocols: Structural subtyping (static duck typing)

### 协议：结构性分型（静态鸭式 typing）

### 内容简述

### 【待阅】

## PEP 557 -- Data Classes

### 数据类

### `@dataclass`

### 【理解】：`collections.namdetuple()` 从此有了大个的傻弟弟

## PEP 560 -- Core support for typing module and generic types

### 键入模块和泛型类型的核心支持

### `typing`

### 【待阅】

## PEP 563 Postponed Evaluation of Annotations

### 延迟的标注求值

### `a: a = ...`

### 【理解】：注解中的前向引用不必再用 `""`

## PEP 572 -- Assignment Expressions

### 赋值表达式

### `:=`

### 【理解】：之前仅有语句可赋值，现在表达式也可赋值

## PEP 614 -- Relaxing Grammar Restrictions On Decorators

### 放宽对装饰器的语法限制

### `@Anything`

### 【理解】：解放装饰器，`@` 可跟任意表达式

## PEP 617 -- New PEG parser for CPython

### 用于 CPython 的新 PEG 解析器

### 新的语法解析器

### 【浏览】

## PEP 634 -- Structural Pattern Matching: Specification

### 结构化模式匹配：规范

### `match ... case:`

### 【理解】：`as` `|` literal capture `_` value `()` sequence mapping class(`__match_args`)

## PEP 635 -- Structural Pattern Matching: Motivation and Rationale

### 结构化模式匹配：动机和理由

### `match ... case:` 的设计考虑

### 【理解】：构造与获取（匹配）的对称

## PEP 636 -- Structural Pattern Matching: Tutorial

### 结构化模式匹配：教程

### `match ... case:` 的教程

### 【理解】：Pythonic 的 switch，使用很便利

## PEP 680 – tomllib: Support for Parsing TOML in the Standard Library

### 支持在标准库中解析 TOML

### **`tomllib.load`** **`tomllib.loads`**

### 【理解】：标准库工具需要读 TOML，但是写操作具有复杂的自由度，所以只读不写

## PEP 3107 -- Function Annotations

### 函数标注

### `__annotations__`

### 【理解】：`identifier [: expression] [= expression]`

## PEP 3115 -- Metaclasses in Python 3000

### Python 3000 中的元类

### `__prepare__()`

### 【理解】：搭配 3.6 引入的 compact dict 可控制类属性创建顺序

## PEP 3119 -- Introducing Abstract Base Classes

### 介绍抽象基类

### `abc`

### 【理解】：抽象基类相关，便于检查具体接口实现情况

## PEP 3129 -- Class Decorators

### 类装饰器

### 类前 `@`

### 【理解】：PEP 318 `@` 只能用在函数和方法前，这里扩展到类

## PEP 3134 – Exception Chaining and Embedded Tracebacks

### 异常链接和嵌入式回溯

###

## PEP 3135 -- New Super

### 新 super

### `super()` `__class__`

### 【理解】：方法内可以直接用 `__class__`，且 `super()` 可省略参数

## PEP 3153 -- Asynchronous IO support

### 异步 IO 支持

### `asyncio`

### 【待阅】

## PEP 3333 -- Python Web Server Gateway Interface v1.0.1

### Python Web 服务器网关接口 v1.0.1

### WSGI

### 【浏览】

## 模板

### 标题翻译

### 内容简述

### 【待阅】【浏览】【理解】


# Python 双刃剑

漫谈 Python 语言特色的优缺点

{% hint style="warning" %}
下文中提到的“Python”均特指官方的 CPython 实现
{% endhint %}

## 解释模式

不同于经典 C 的编译模式，Python 是以解释模式运行的。也就是说，只有在实际运行时解释器才会逐行读取对应的代码。

#### 优点

1. 所见即所得，符合直观逻辑（线性顺序执行）。
2. 提升了 DEBUG 效率（支持动态修正）。
3. 简化了开发流程（除去了编译环节）。

#### 缺点

1. 显著降低了运行时效率（无法进行任何的编译时优化）。
2. 增大了制作独立程序包的难度（需要内嵌整个解释器）。

## 动态类型

在 Python 中使用变量不需要任何额外的步骤来声明其类型，变量的实际类型由解释在运行时动态判断且可以发生变动。

#### 优点

1. 简化语法（Pythonic 的核心就是简洁之美）。
2. 显著提升小项目的代码开发效率（无需设计全套的类型接口）。

#### 缺点

1. 影响代码运行的时间和空间效率（需要额外的类型检查；即使是很小的变量也需要存储额外的对象结构数据）。
2. 对于后期维护升级不友好（函数签名包含的信息过少，必须依赖额外文档）。
3. 为 BUG 的存活提供了良好的环境（错误的传参和调用可能不被发现）。

## GIL

Global Interpreter Lock（全局解释器锁）是 CPython 解释器所采用的一种机制，它确保同一时刻只有一个线程在执行 Python bytecode。

#### 优点

1. 使得解释器多线程运行更方便（事实上将底层对象访问转化为了单线程）。

#### 缺点

1. 牺牲了在多处理器上的并行性（一核有难，七核围观）。


# 类型标注

## 序言

编程语言界最常见到的动态类型语言莫过于 Javascript 和 Python，尽管二者在其设计哲学、应用领域方面有着巨大的差异，但随着它们用户基数的增长，都出现了一个相同的发展趋势——类型静态化。对于 Javascript 来说，Typescript 的出现就是最好的例子；而对于 Python 而言，由 PEP 484 在标准库中引入的 `typing` 模块也可见一斑。

好好的动态类型，为什么都要朝着静态类型发展呢？

一言以概之：“**动态类型写着爽，维护升级火葬场**”。

就以我们的主角 Python 而言，在其发展早期，它只不过是作为一个小小的工具语言，用以在大型项目中的边边角角做一些简单的辅助性处理。那时的 Python，一般也就是个两三千行撑死，莫说是复杂的类型结构，很可能连 `class` 语句都不会出现。在这种基本就是内置类型传来传去的情况下，动态类型让老练的开发者能够快速高效地完成简单的工作，一时之间受到了大家的追捧。

伴随着 Python 的流行，越来越多的项目采用 Python 作为主语言。而当一个项目拥有过万行的代码量以及完整而精巧的类型结构设计时，动态类型的弊端就开始显现。函数签名的自解释性匮乏，开发者不得不“面向文档编程”；错误的类型传递无法避免，隐藏的 BUG 开始积累；类型的含义逐步被淡化，精心构造的类型结构失去价值……这时候，大家又开始怀念起了静态类型的好，写代码时多跳几个 `type error` 总好过 DEBUG 时抓心挠肺。

在这段时期，一个名叫 mypy 的第三方包的兴起令 Python 核心开发者意识到了真正的问题所在：**码农们对于静态类型的偏好其实源于对类型检查器的依赖**。mypy 就是一个静态类型检查器，通过解析 Python 代码及其中包含的特定的注释，在 Python 代码实际运行前进行静态的类型检查。而这是一个兼容性非常棒的解决方案：类型声明的内容均包含在注释中，不会对原有的代码含义产生任何影响；类型检查独立工作在代码运行前，不会对代码的实际运行产生任何影响。2014 年 9 月 29 日，Python 之父 Guido van Rossum、mypy 之父 Jukka Lehtosalo 及 Python 核心开发者 Łukasz Langa 联手发布了 [PEP 484 -- Type Hints](https://www.python.org/dev/peps/pep-0484/) ，在 Python 标准库中引入了全新的 `typing` 模块，提供对类型标注的官方支持。

时至今日，类型标注已经成为 Python 的核心语言特性之一，但相关的中文资料多是只言片语，缺乏系统性的介绍，故开此篇以作补充。

{% hint style="info" %}
本文内容基于 Python 3.10.2
{% endhint %}

## 引入类型标注的动机

Python 项目中需要引入类型检查以维持项目的可持续发展，但是不应为此改变 Python 自诞生以来的动态语言特征。而社区中已有被广泛接受的解决方案：在源代码中使用注释补充变量信息，检查器在代码运行前进行（静态）类型检查。

静态类型检查的高度实用性与优雅性赢得了整个 Python 社区的青睐，故而 Python 核心开发者们决定在核心语法特性中引入官方支持。

但需要强调的是，**类型标注** 与静态类型语言中的 *变量声明* 不尽相同，且这不会动摇 Python 一直以来作为动态类型语言的本质与设计哲学。

> **Python 将仍然是一种动态类型的语言，作者不希望强制类型提示，即使按照惯例也是如此。**
>
> **——PEP 484**

> **类型注释不应与静态类型语言中的变量声明相混淆。注释语法的目标是提供一种简单的方法来为第三方工具指定结构化类型元数据。**
>
> **——PEP 526**

## 类型标注的理论基础

Python 所采用的类型标注运用了 **渐进式类型（Gradual Typing）** 理论。

常见编程语言对类型检查的实现，存在两个派别——动态类型检查与静态类型检查。

动态类型检查的代表性语言包括 Perl、Python、Javascript、Ruby 和 PHP，“动态”的含义是类型检查发生在程序代码实际执行期间，即对内存中已经存在的数据进行操作时才对其类型进行检查。

静态类型检查的代表性语言包括 Java、C#、C 和 C++，“静态”的含义是类型检查发生在程序代码实际执行之前，此时内存中并没有实际生成对应数据。

这两派的支持者间关于谁优谁劣的争论已经持续了数十年，至今仍为得出一致的结论。

{% hint style="info" %}
个人认为这场争论的核心是围绕 **开发效率、运行效率、维护效率** 的取舍：动态类型检查以损失运行效率和维护效率为代价，大大提升了开发效率；静态类型检查以较大的开发效率损失换来了更高的运行效率和维护效率。尽管偏好相异，但二者都对开发效率做出了相对极端的取舍。
{% endhint %}

[Jeremy Siek](https://wphomes.soic.indiana.edu/jsiek/) 与 Walid Taha 联手在 2006 年提出了渐进式类型理论，该理论结合了动态类型检查和静态类型检查

区分类与类型

类型继承与子类型

## 语法详解

在介绍语法之前，我们需要先区分两个易混淆的概念—— **类** 和 **类型。**

在 Python 中，类是由 `class` 语句定义的对象工厂，并由 `type(obj)` 内置函数返回。类是一个动态的、运行时的概念。具体可参见作者另一篇博文 [你真的“创建”了类吗？](/python/create-class)

类型是用于描述对象特征的抽象概念，拥有一系列相同的功能、值的对象可以归为一个类型。类型是一个静态的、逻辑性的概念。

{% hint style="danger" %}
“类型标注”这个名称已经明确表明了其标注的内容是类型而非类，所以一定要注意，**应将类型标注中使用的名称作为类型而非简单的类来看待**。
{% endhint %}

### 变量

### 函数

### 方法

## 高级特性

### 泛型

### TypeGuard

###

## 参考

1. [typing --- 类型提示支持](https://docs.python.org/zh-cn/3/library/typing.html)
2. [PEP 483 -- The Theory of Type Hints](https://www.python.org/dev/peps/pep-0483/)
3. [PEP 484 -- Type Hints](https://www.python.org/dev/peps/pep-0484/)
4. [PEP 526 -- Syntax for Variable Annotations](https://www.python.org/dev/peps/pep-0526/)
5. [PEP 544 -- Protocols: Structural subtyping (static duck typing)](https://www.python.org/dev/peps/pep-0544/)
6. [PEP 585 -- Type Hinting Generics In Standard Collections](https://www.python.org/dev/peps/pep-0585/)
7. [PEP 586 -- Literal Types](https://www.python.org/dev/peps/pep-0586/)
8. [PEP 589 -- TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys](https://www.python.org/dev/peps/pep-0589/)
9. [PEP 591 -- Adding a final qualifier to typing](https://www.python.org/dev/peps/pep-0591/)
10. [PEP 593 -- Flexible function and variable annotations](https://www.python.org/dev/peps/pep-0593/)
11. [PEP 604 -- Allow writing union types as X | Y](https://www.python.org/dev/peps/pep-0604/)
12. [PEP 612 -- Parameter Specification Variables](https://www.python.org/dev/peps/pep-0612/)
13. [PEP 613 -- Explicit Type Aliases](https://www.python.org/dev/peps/pep-0613/)
14. [PEP 647 -- User-Defined Type Guards](https://www.python.org/dev/peps/pep-0647/)
15. [What is Gradual Typing](https://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/)


# “类”的渐进式剖析

PyCon China 2023 主题演讲

类是面向对象编程中的核心概念，更是 Python 中不可或缺的一部分。 几乎每一个 Python 用户都曾写过 class 语句，但你可曾想过在这个优雅的语句下，到底包装了怎样的底层设计和实现？ 本文将以自顶向下的形式，从最基础的类构建顺序展开，渐进式地深入元类、属性/方法解析顺序、描述器、C3—MRO 算法等多个极其重要的底层概念。 随后，我们将在此基础上展开 typing 类型注解中的类型系统理论，并尝试探讨关于 None 值的开放性问题。

### 0o10 你真的“创建”了类吗？

*类*是 OOP（面向对象编程）的核心概念，更是 Python 中不可或缺的一部分。

一般情况下我们会这样“创建”类：

```python
class A(object):  # Python 3 的类默认继承自 object
    ...
```

然后我们就可以用 `A` 这个名称来引用这个类了，类似于这样：

```python
a = A()
```

如果我们抛开 `A` 作为类的特殊身份，单独审视上面这个语句。 根据基础的变量引用语法，既然能够引用 `A` 这个名字，那么必然发生了针对于 `A` 的赋值。 也许你会觉得这背后是一个类似于 `A = class ...` 语法糖，但要知道 `class` 语句并不能作为合法的右值。

想要了解真相，这一切都还要从 Python 中类的具体概念说起：

> 在 Python 中，类是由 class 语句定义的对象工厂，并由 type(obj) 内置函数返回。 是一个动态的、运行时的概念。 —— PEP 483

准确地说，`class` 语句只是定义了类，但此时语句块里的内容还只是静态的、运行前的声明。 所以我们并没有直接“创建”类，准确地说，我们只是设计了类。 真正创建类的操作是在代码实际运行的过程中，由解释器完成的。

解释器实际创建的类本质上是 `type` 的一个对象，称为 **类对象**，它正是上文中 `A =` 中等号右侧的内容。

*注意这里说的“类对象”不是“类实例”，类对象指的是类型本身作为一个对象，而类实例是指类型的实例化后的生成的、从属于类型的对象。*

那么从 `class` 语句到最终的类对象生成，解释器都做了些什么呢？ 最直观的莫过于标准库模块 `types` 的源码了：

```python
# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
    """Create a class object dynamically using the appropriate metaclass."""
    resolved_bases = resolve_bases(bases)
    meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
    if exec_body is not None:
        exec_body(ns)
    if resolved_bases is not bases:
        ns['__orig_bases__'] = bases
    return meta(name, resolved_bases, ns, **kwds)

def resolve_bases(bases):
    """Resolve MRO entries dynamically as specified by PEP 560."""
    new_bases = list(bases)
    updated = False
    shift = 0
    for i, base in enumerate(bases):
        if isinstance(base, type):
            continue
        if not hasattr(base, "__mro_entries__"):
            continue
        new_base = base.__mro_entries__(bases)
        updated = True
        if not isinstance(new_base, tuple):
            raise TypeError("__mro_entries__ must return a tuple")
        else:
            new_bases[i+shift:i+shift+1] = new_base
            shift += len(new_base) - 1
    if not updated:
        return bases
    return tuple(new_bases)

def prepare_class(name, bases=(), kwds=None):
    """Call the __prepare__ method of the appropriate metaclass.

    Returns (metaclass, namespace, kwds) as a 3-tuple

    *metaclass* is the appropriate metaclass
    *namespace* is the prepared class namespace
    *kwds* is an updated copy of the passed in kwds argument with any
    'metaclass' entry removed. If no kwds argument is passed in, this will
    be an empty dict.
    """
    if kwds is None:
        kwds = {}
    else:
        kwds = dict(kwds) # Don't alter the provided mapping
    if 'metaclass' in kwds:
        meta = kwds.pop('metaclass')
    else:
        if bases:
            meta = type(bases[0])
        else:
            meta = type
    if isinstance(meta, type):
        # when meta is a type, we first determine the most-derived metaclass
        # instead of invoking the initial candidate directly
        meta = _calculate_meta(meta, bases)
    if hasattr(meta, '__prepare__'):
        ns = meta.__prepare__(name, bases, **kwds)
    else:
        ns = {}
    return meta, ns, kwds

def _calculate_meta(meta, bases):
    """Calculate the most derived metaclass."""
    winner = meta
    for base in bases:
        base_meta = type(base)
        if issubclass(winner, base_meta):
            continue
        if issubclass(base_meta, winner):
            winner = base_meta
            continue
        # else:
        raise TypeError("metaclass conflict: "
                        "the metaclass of a derived class "
                        "must be a (non-strict) subclass "
                        "of the metaclasses of all its bases")
    return winner
```

#### 0o11 类的创建流程

1. **执行到类定义代码**
2. **解析 MRO 条目**
3. **确定适当的元类**
4. **准备类命名空间**
5. **执行类主体**
6. **创建类对象**
7. **准备执行后续代码**

#### 0o12 元类存在的必要性

在 OOP 中，动态的类创建是偏向于底层的高级概念。\
OOP 的核心是 **“万物皆对象”** ，而类作为程序员设计并使用的基础工具，也应该被视为对象。\
那么自然，**类对象** 需要有他的类，而这个类就是 **元类**。\
元类是留给类设计者的最底层概念，在其之下的都属于具体语言的实现，不再是 OOP 应该关注的内容。

而相较于 Java 等语言的反射机制，Python 选择直接将一部分类的创建流程公开给程序员，无疑是秉承了 **“显示优于隐式”** 的哲学。\
尽管在平常的使用中普通程序员很少会直接去影响类的创建，但在很多复杂而神奇的包开发中这却是不可或缺的工具。\
而事实上这的确成为了 Python 的 **重要优势** 之一，至今元类的应用非常广泛，包括且不限于 \_枚举、日志、接口检查、自动委托、自动特征属性创建、代理、框架以及自动资源锁定/同步 \_等等。

#### 0o13 元类使用中的问题及优化方式

首先，**元类是一个相当复杂的概念**。即便你已经对此有所了解，但实际应用时总还是会出现各种各样的问题，而且这些个问题往往会是由于底层概念上的递归造成的。

其次，**没有自动方法可以组合元类**。如果要为一个类使用两个元类，则通常需要手动创建一个将这两个类合并在一起的新元类。\
这种需求常常使用户感到意外：从两个不同的库继承的两个基类继承突然增加了手动创建组合元类的必要性，通常情况下，人们对这些库的那些细节完全不感兴趣。\
如果一个库开始使用以前从未使用过的元类，这将变得更加糟糕。当库本身继续正常工作时，将这些类与另一个库中的类组合在一起的每个代码突然都失败了。

尽管有多种使用元类的方法，但绝大多数用例可分为三类：

1. 在类创建后运行的一些初始化代码
2. 描述器的初始化
3. 保持类属性定义的顺序

事实上为了满足这些需求，我们 **未必就非用元类不可**。

通过对类的创建进行简单的 **挂钩** 就可以轻松实现前两个类别：

一个 `__init_subclass__` 挂钩初始化一个给定类的子类。\
创建类时，对类中定义的所有属性（描述符）调用 `__set_name__` 挂钩。

而第三个类别自从 Python 3.6 进行了 compact dict 的优化使 `dict` 类型默认保留插入顺序后，通过 `__prepare__` 也完全可以满足。

{% hint style="success" %}
**在当前的版本中，元类不再是我们深度定制类创建的唯一选择，活用以下这三个魔法方法，你就可以和元类说再见了：**

* `__init_subclass__`
* `__set_name__`
* `__prepare__`
  {% endhint %}

### 0o20 基于过程如何面向对象？

> 面向对象设计有三个基本特征：封装、继承和多态。 ——《设计模式：可复用面向对象软件的基础》

Python 是一门基于解释器的语言，也就是我们常说的“脚本语言”。 作为脚本语言，Python 的解释器需要逐行读取代码并顺序执行，所以 Python 的底层语言设计是基于过程的。 *请注意这里提到的是“底层语言设计”，而非“底层实现”。因为无论语言本身多么花哨，CPU 最终执行的机器码仍是面向操作的，而面向操作可以说是面向过程的一个子集，所以从本质上来说，所有语言的底层实现都是基于过程的。* 同时，xx

Linus 所强调的“Nothing better than C” 不严谨地讲，对象是过程上的再封装

#### 0o21 `struct` 与 `class` 的对比

封装是共有的，因为“继承、多态”其实就是封装的一种实现方式。

对比 “.” 语法关联的 struct 和 class

1. 表面的 self 传入
2. 继承与多态

#### 0o22 描述器

描述器不仅是个简单的 hook，更多的要涉及到属性查找顺序，进而到mro c3-mro算法 面向对象，但是又把类当作聚合隔离的工具，所以就有了 类对象

#### 0o23 属性访问顺序

面向对象与面向过程的重要区别之一就是`something.attribute`形式的调用，这被称为属性调用，这里的属性是指广义上的，**包括基础属性和方法**。

**对象属性访问顺序**

1. 依照 **MRO** 顺序的类的类属性中的 **数据描述器属性**
2. **实例对象的属性**`object.__dict__`
3. 依照 MRO 顺序的类的类属性中的 **非数据描述器属性**
4. 依照 MRO 顺序的类的类属性中的 **普通（非描述器）属性**`cls.__dict__`

**类属性访问顺序**

1. 依照元类的 MRO 顺序的类的类属性中的 **元类数据描述器属性**
2. 依照 MRO 顺序的类的类属性中的 **数据描述器属性**
3. 依照 MRO 顺序的类的类属性中的 **普通（非描述器）属性**`cls.__dict__`
4. 依照 MRO 顺序的类的类属性中的 **非数据描述器属性**
5. 依照元类的 MRO 顺序的类的类属性中的 **元类非数据描述器属性**

{% hint style="info" %}
Python 中 **类的本质是元类创建的对象**，所以相当于是外面套了一层不包含普通属性（亦即非描述器属性）的对象属性访问顺序。
{% endhint %}

#### 0o24 C3-MRO

{% hint style="info" %}
**方法解析顺序（Method Resolution Order, MRO）** 是在 **面向对象编程** 中，当某个实例对象应用了继承，进而引发 **多态** 特性时，编译/解释器 **查找并决定具体实例方法的顺序** 。
{% endhint %}

一般情况下所提到的 MRO 基本都是指复杂多继承中的 MRO，其本质是 **一个顺序**，**可用具体编程语言中的序列来表示（Python 中就是 `collections.abc.Sequence`）**，本文同一般情况。

MRO 的作用：

* 实现方法重载
* 构建 OOP 多态
* 保证继承有效

### 0o30 路在何方？

在前文的基础上，我们可以展开一些开放性的探讨。

#### 0o31 类型标注 `typing` 何以成为大势所趋？

起源于大规模代码维护 一言以概之：“**动态类型写着爽，维护升级火葬场**”。 就以我们的主角 Python 而言，在其发展早期，它只不过是作为一个小小的工具语言，用以在大型项目中的边边角角做一些简单的辅助性处理。那时的 Python，一般也就是个两三千行撑死，莫说是复杂的类型结构，很可能连 `class` 语句都不会出现。在这种基本就是内置类型传来传去的情况下，动态类型让老练的开发者能够快速高效地完成简单的工作，一时之间受到了大家的追捧。

伴随着 Python 的流行，越来越多的项目采用 Python 作为主语言。而当一个项目拥有过万行的代码量以及完整而精巧的类型结构设计时，动态类型的弊端就开始显现。函数签名的自解释性匮乏，开发者不得不“面向文档编程”；错误的类型传递无法避免，隐藏的 BUG 开始积累；类型的含义逐步被淡化，精心构造的类型结构失去价值……这时候，大家又开始怀念起了静态类型的好，写代码时多跳几个 `type error` 总好过 DEBUG 时抓心挠肺。

在这段时期，一个名叫 mypy 的第三方包的兴起令 Python 核心开发者意识到了真正的问题所在：**码农们对于静态类型的偏好其实源于对类型检查器的依赖**。mypy 就是一个静态类型检查器，通过解析 Python 代码及其中包含的特定的注释，在 Python 代码实际运行前进行静态的类型检查。而这是一个兼容性非常棒的解决方案：类型声明的内容均包含在注释中，不会对原有的代码含义产生任何影响；类型检查独立工作在代码运行前，不会对代码的实际运行产生任何影响。2014 年 9 月 29 日，Python 之父 Guido van Rossum、mypy 之父 Jukka Lehtosalo 及 Python 核心开发者 Łukasz Langa 联手发布了 [PEP 484 -- Type Hints](https://www.python.org/dev/peps/pep-0484/) ，在 Python 标准库中引入了全新的 `typing` 模块，提供对类型标注的官方支持。

> Type concept is described above, types appear in variable and function type annotations, can be constructed from building blocks described below, and are used by static type checkers. 类型概念如上所述，类型出现在变量和函数类型注释中，可以从下面描述的构建块构造，并由静态类型检查器使用。

> In Python, classes are object factories defined by the `class` statement, and returned by the `type(obj)` built-in function. Class is a dynamic, runtime concept. 在 Python 中，类是由 class 语句定义的对象工厂，并由 type(obj) 内置函数返回。 是一个动态的、运行时的概念。 —— PEP 483

1. Python 中由 Type Hints 及其标志性的 `typing` 模块代表的类型化是一种自顶向下的过程，从某种角度上来讲，这算是一种动态类型到静态类型的逆向工程
2. 常见的强类型语言中 则是 自底向上
3. 渐进式类型标注 Gradual typing allows one to annotate only part of a program, thus leverage desirable aspects of both dynamic and static typing. 渐进式类型化允许仅注解程序的一部分，从而充分利用动态和静态类型化的优点。 本文题目也正是自此而来。

除此之外还有更多的用途：

1. 被用于以 dataclass，Pydantic 为代表的 Model 式定义
2. 被用于以 LPython 为代表的性能（编译）优化
3. 或将被用于文档字符注释 [PEP 727 – Documentation in Annotated Metadata](https://peps.python.org/pep-0727/)

#### 0o32 None 为何如此棘手？

如果说 `NULL` 价值十亿美元，那么 Python 中的 `None` 少说也得价值百万美元。 不同于 C 中的指针与内存安全问题，Python 中 `None` 的问题主要出现在类型方面。

子类型关系

> every value from second\_type is also in the set of values of first\_type; second\_type 中的每个值也在 first\_type 的值集中； every function from first\_type is also in the set of functions of second\_type. first\_type 中的每个函数也在 second\_type 的函数集中。

推论

> 1. Every type is a subtype of itself.
> 2. 每种类型都是其自身的子类型。
> 3. The set of values becomes smaller in the process of subtyping, while the set of functions becomes larger.
> 4. 在子类型化的过程中，值的集合变得更小，而函数的集合变得更大。 pep483

> When used in a type hint, the expression None is considered equivalent to type(None). 当在类型提示中使用时，表达式 None 被视为等同于 type(None) 。 pep484

客观问题 None 的存在违反了值和方法集合的变化规律，打破了原有的类型系统.

主观问题 很多时候其实它的作用只是一个 sentinel `if` 的简便写法忽略了类型问题 `if None` `if []` 同为假

### 0o40 参考资料

#### 0o41 PEP

* [PEP 253 -- Subtyping Built-in Types](https://www.python.org/dev/peps/pep-0253/)
* [PEP 318 -- Decorators for Functions and Methods](https://www.python.org/dev/peps/pep-0318/)
* [PEP 483 -- The Theory of Type Hints](https://www.python.org/dev/peps/pep-0483/)
* [PEP 487 -- Simpler customisation of class creation](https://www.python.org/dev/peps/pep-0487/)
* [PEP 520 – Preserving Class Attribute Definition Order](https://peps.python.org/pep-0520/)
* [PEP 560 – Core support for typing module and generic types](https://peps.python.org/pep-0560/)
* [PEP 727 – Documentation in Annotated Metadata](https://peps.python.org/pep-0727/)
* [PEP 3115 -- Metaclasses in Python 3000](https://www.python.org/dev/peps/pep-3115/)
* [PEP 3129 – Class Decorators](https://www.python.org/dev/peps/pep-3129/)

#### 0o42 官方文档

* [数据模型](https://docs.python.org/zh-cn/3/reference/datamodel.html)
* [描述器使用指南](https://docs.python.org/zh-cn/3/howto/descriptor.html)
* [The Python 2.3 Method Resolution Order](https://www.python.org/download/releases/2.3/mro/)

#### 0o43 三方文档

* [The paper A Monotonic Superclass Linearization for Dylan](https://doi.org/10.1145/236337.236343)
* [C3 线性化算法与 MRO——理解Python中的多继承](http://kaiyuan.me/2016/04/27/C3_linearization/)
* [C3 linearization](https://en.wikipedia.org/wiki/C3_linearization)
* [The thread on python-dev started by Samuele Pedroni](https://mail.python.org/pipermail/python-dev/2002-October/029035.html)
* [Python 方法解析顺序MRO-C3算法](https://xubiubiu.com/2019/06/10/python-%E6%96%B9%E6%B3%95%E8%A7%A3%E6%9E%90%E9%A1%BA%E5%BA%8Fmro-c3%E7%AE%97%E6%B3%95/)
* [python高级编程——描述符Descriptor详解（上篇）——python对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84848341)
* [python高级编程——描述符Descriptor详解（中篇）——python对象的属性访问优先级与属性的控制与访问）](https://blog.csdn.net/qq_27825451/article/details/84767061)
* [python高级编程——描述符Descriptor详解（下篇）——python描述符三剑客详解](https://blog.csdn.net/qq_27825451/article/details/84848341)
* [python高级编程——描述符Descriptor详解（补充篇）——python描述符实现一些底层高级功能](https://blog.csdn.net/qq_27825451/article/details/84848341)
* [描述器](https://www.dazhuanlan.com/2020/02/29/5e5965cea4d60/)
* [Python中的类与描述器(Descriptors)](https://blog.csdn.net/u013008795/article/details/90646667)
* [Python 3.11 更快的 CPython](https://www.white-winds.com/post/python%203.11%20fast%20cpython/)
* [PyConChina2022-深圳-大规模生产环境下的Faster CPython-王文洋](https://github.com/PyConChina/2022-slides/blob/main/Shenzhen/PyConChina2022-%E6%B7%B1%E5%9C%B3-%E5%A4%A7%E8%A7%84%E6%A8%A1%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%8B%E7%9A%84Faster%20CPython-%E7%8E%8B%E6%96%87%E6%B4%8B.pdf)
* [NULL: The Billion Dollar Mistake](https://hackernoon.com/null-the-billion-dollar-mistake-8t5z32d6)

#### 0o44 个人博客

* [你真的“创建”了类吗？](https://blog.wh2099.com/python/create-class)
* [MRO 三定律](https://blog.wh2099.com/python/c3-mro)
* [描述器学习指南](https://blog.wh2099.com/python/descriptor)
* [描述器实现 property](https://blog.wh2099.com/python/property)
* [类型标注](https://blog.wh2099.com/python/typing)


# IPv6

此篇内容较杂，尚在整理中😊


# 大道至简

网络时代软件变革之道

## 前言

作为一个版本控，咱向来是用新不用旧。一方面这直接导致咱大量的时间消耗在软件升级及适应新版本上，另一方面这也让咱拥有了相对丰富的软件升级的经验。

![](/files/-Mhs_kYTDzkixNPHV4zm)

在由各类软件“最新版本”、“开发版本”乃至于“不兼容替代品”搭建成的华丽但脆弱的扑克山上长期居住，个中辛酸，人生百味，不必多言。

就说说好的一面吧，咱已经实现了数据全面上云，并且掌握了熟练的数据恢复、系统重装、应用部署技术，除此之外还培养了较高的情绪控制力。

只要承载核心数据的微软 Onedrive 不出问题，软件 Bug 引发的数据丢失、软件损坏、系统崩溃，都是过眼云烟；物理层面的硬件损坏，不以介怀；哪怕是心理上的损害，也能自舐伤口。

这么多年的折腾，也该反思总结一下了。故开此篇谈一谈对于软件变革之道的认识。

{% hint style="info" %}
受限于个人能力 XD，文中图片均取自网络，侵删
{% endhint %}

## 何为变革？

### 概念

**变革就是引入了影响较大的不向后兼容更改的升级**。用语义化版本（Semantic Versioning）来具体说明，就是**引起主版本号变更的升级**。

![语义化版本（Semantic Versioning）](/files/-MiG4ExzLHWAD0N7U4_3)

### 事例

* **编程语言**：Python2 -> Python3
* **网络协议**：IPv4 -> IPv6
* **操作系统**：Windwos -> Linux
* **管理框架**：iptables -> nftables
* **日常应用**：QQ -> 微信

## 作茧自缚还是化茧成蝶？

如果把软件升级的过程比作昆虫成长的过程，变革就相当于“变态发育”的环节。

在高速发展的现代信息化社会，海量的的电子数据在错综复杂的信道上光速汹涌，而支撑起这一切的网络架构，也在巨浪的澎湃下不断改变。在这样的时代背景下，每一秒都有胸怀改变世界之梦的同志发起软件变革，但现实是残忍的，绝大多数变革最终的结局仍是**作茧自缚**，仅有为数不多的变革能够**化茧成蝶**，一飞冲天。

![](/files/IsBrq1P35OB6gA8aC4h3)

那么，到底是什么撑起了这对能够引发飓风的翅膀呢？

> **“妙言至径，**<mark style="color:red;">**大道至简**</mark>**。”** ——《还金述》

## 为何简？

这就要从咱对于“**人类**”这个概念的理解谈起了。

对于自我的探求，恐怕从我们的祖先拥有思考能力的那一刹那就已经开始，而在近代，更是为此特化了一门名为“人类学”的学科。不妨先来看看教科书上是怎么写的：

> 能够使用语言、具有复杂的社会组织与科技发展的生物，尤其是他们能够建立团体与机构来达到互相支持与协助的目的。

很标准，但咱并不喜欢这种拗口又死板的定义，咱认为，应该再简化下，“**地球上的一种生物**”，仅此而已。

独拥智慧果实？早已有科学证明，猩猩也能达到人类幼体的智慧水平。

唯一社会体系？楼下蚂蚁第一个不服。

丰富情感能力？解释下你家宠物。

{% hint style="warning" %}
*以上内容仅为调侃，请勿当真 XD*
{% endhint %}

那么仅作为一个生物而谈，根据现有的理论共识，生物个体具有不可抗拒的生存本能，在此基础上，生物群体为了与概率抗争，演化出了扩张的本能。也就是群体会无限制追求更大的种群基数、更广的领地。

*作为万物之灵，人类在这方面可谓是再典型不过，不是吗？*

**扩张的本能是无限的，但现实中当前人类所接触的一切都是有限的**。面对无限与有限的矛盾，人类通过利用自己的特长，也就是高等智慧，很快就发现了“**效率**”的概念：

$$
效率=\frac{产出}{投入}
$$

那么为了追求无限大的扩张，人类就需要首先达到无限大的效率。而从等式不难看出，效率增长需要**更高的产出**和**更低的投入**。以批判式的用词对应到现实中人类的品质，其实也就是“**贪婪**”与“**懒惰**”。

$$
效率 \to +\infty \ \Downarrow \ 产出 \to +\infty \quad \And \quad 投入 \to -\infty
$$

{% hint style="warning" %}
或许是因为人类集体意识中自我否定的一面，在寻找合适的词语去描述人类的本质时，总是会归根于类似“七宗罪”的用词。但需要强调的是，咱也不想使用这种高度贬义的词汇，因为**咱并不认为这种本质是负面的**。
{% endhint %}

有了以上的展开，我们就可以继续对于“简”的讨论了。

## 何为简？

### 扁平化

### 低依赖


# DNS 根域

DNS 根域由 IANA 管理

## <https://www.iana.org/domains/root/files>


# RFC 阅读清单

Request for Comments

{% hint style="success" %}
[**\[译\] 如何阅读 RFC 文档**](https://juejin.cn/post/6844903716051484679)
{% endhint %}

## BCP 14 - Key words for use in RFCs to Indicate Requirement Levels

### 在 RFC 中用于指示需求级别的关键字

### "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL"

### 【理解】：绝对 通常 可选

## RFC 495 - TELNET Protocol Specification

### TELNET 协议规范

### TELNET 协议

### 【浏览】

## RFC 959 - FILE TRANSFER PROTOCOL (FTP)

### 文件传输协议（FTP）

### FTP 协议

### 【待阅】

## RFC 2516 - A Method for Transmitting PPP Over Ethernet (PPPoE)

### 一种通过以太网传输 PPP (PPPoE) 的方法

### PPPoE

### 【浏览】

## RFC 3659 - Extensions to FTP

### FTP 扩展

### 拓展了新的 FTP 命令

### 【待阅】

## RFC 5218 - What Makes for a Successful Protocol?

### 是什么使协议成功？

### 总结优秀协议的特点

### 【浏览】

## RFC 5234 - Augmented BNF for Syntax Specifications: ABNF

### 语法规范的增强型 BNF：ABNF

### ABNF 语法规范

### 【理解】：/ 或，\[ ] 可选，n\*m 重复，; 注释

## 模板

### 标题翻译

### 内容简述

### 【待阅】【浏览】【理解】


# 基础公共服务

DNS NTP

{% hint style="info" %}
**入选需均满足以下条件：**

* **服务内容符合相关互联网标准**
* **运行时间长，故障率低**
* **被广泛认可**
  {% endhint %}


# DNS

Domain Name System 域名系统

## **国内 DNS 服务器**

### [**阿里 DNS**](https://www.alidns.com)\*\*\*\*

| **IPv4**        | **IPv6**                |
| --------------- | ----------------------- |
| **`223.5.5.5`** | **`2400:3200::1`**      |
| **`223.6.6.6`** | **`2400:3200:baba::1`** |

| **DoH**                                | **DoT**              |
| -------------------------------------- | -------------------- |
| **`https://dns.alidns.com/dns-query`** | **`dns.alidns.com`** |

### [**DNSPod Public DNS（腾讯云）**](https://docs.dnspod.cn)

| **IPv4**           | **IPv6**          |
| ------------------ | ----------------- |
| **`119.29.29.29`** | **`2402:4e00::`** |

| **DoH**                         | **DoT**       |
| ------------------------------- | ------------- |
| **`https://doh.pub/dns-query`** | **`dot.pub`** |

### [**百度 DNS**](https://dudns.baidu.com)

| **IPv4**           | **IPv6**              |
| ------------------ | --------------------- |
| **`180.76.76.76`** | **`2400:da00::6666`** |

### [**114 DNS**](https://www.114dns.com)

| **无劫持**               | **安全**                | **未成年**               |
| --------------------- | --------------------- | --------------------- |
| **`114.114.114.114`** | **`114.114.114.119`** | **`114.114.114.110`** |
| **`114.114.115.115`** | **`114.114.115.119`** | **`114.114.115.110`** |

### [SDNS](https://www.sdns.cn)

| **IPv4**        | IPv6                   |
| --------------- | ---------------------- |
| **`1.2.4.8`**   | **`2001:dc7:1000::1`** |
| **`210.2.4.8`** |                        |

### [**Quad 101**](https://101.101.101.101)

| **IPv4**              | **IPv6**            |
| --------------------- | ------------------- |
| **`101.101.101.101`** | **`2001:de4::101`** |
| **`101.102.103.104`** | **`2001:de4::102`** |

## 国外 DNS 服务器

### [**Cloudflare DNS**](https://1.1.1.1/dns/)

| **IPv4**      | **IPv6**                   |
| ------------- | -------------------------- |
| **`1.1.1.1`** | **`2606:4700:4700::1111`** |
| **`1.0.0.1`** | **`2606:4700:4700::1001`** |

### [**Google Public DNS**](https://dns.google)

| **IPv4**      | **IPv6**                   |
| ------------- | -------------------------- |
| **`8.8.8.8`** | **`2001:4860:4860::8888`** |
| **`8.8.4.4`** | **`2001:4860:4860::8844`** |

| **DoT**          | **DoH**                            |
| ---------------- | ---------------------------------- |
| **`dns.google`** | **`https://dns.google/dns-query`** |

### [OpenDNS（Cisco）](https://www.opendns.com)

| **IPv4**             |
| -------------------- |
| **`208.67.222.222`** |
| **`208.67.220.220`** |

### [Quad9](https://www.quad9.net)

| **IPv4**              | **IPv6**          |
| --------------------- | ----------------- |
| **`9.9.9.9`**         | **`2620:fe::fe`** |
| **`149.112.112.112`** | **`2620:fe::9`**  |


# NTP

Network Time Protocol 网络时间协议

## 国内 NTP 服务器

### [国家授时中心](http://www.ntsc.cas.cn)

#### `ntp.ntsc.ac.cn`

### [**NTP.ORG.CN**](http://www.ntp.org.cn)

#### `cn.ntp.org.cn`

### [Pool NTP ORG](https://www.pool.ntp.org/zone/cn)

#### `cn.pool.ntp.org`

### [阿里云](https://help.aliyun.com/document_detail/92704.html)

#### `time.pool.aliyun.com`

#### `time1.aliyun.com`

#### `time2.aliyun.com`

#### `time3.aliyun.com`

#### `time4.aliyun.com`

#### `time5.aliyun.com`

#### `time6.aliyun.com`

#### `time7.aliyun.com`

### [腾讯云](https://cloud.tencent.com/document/product/213/30392)

#### `time1.cloud.tencent.com`

#### `time2.cloud.tencent.com`

#### `time3.cloud.tencent.com`

#### `time4.cloud.tencent.com`

#### `time5.cloud.tencent.com`

### 中国教育网（各高校）

#### `ntp.sjtu.edu.cn`

#### `ntp.neu.edu.cn`

#### `ntp.bupt.edu.cn`

#### `ntp.shu.edu.cn`

## 国际 NTP 服务器

### 国际教育网

#### `edu.ntp.org.cn`

### [Pool NTP ORG](https://www.ntppool.org)

#### `pool.ntp.org`

#### 0.pool.ntp.org

#### 1.pool.ntp.org

#### 2.pool.ntp.org

#### 3.pool.ntp.org

#### `asia.pool.ntp.org`

### [谷歌](https://developers.google.com/time)

#### `time1.google.com`

#### `time2.google.com`

#### `time3.google.com`

#### `time4.google.com`

### [苹果](https://developer.apple.com/documentation/devicemanagement/timeserver)

#### `time.apple.com`

#### `time1.apple.com`

#### `time2.apple.com`

#### `time3.apple.com`

#### `time4.apple.com`

#### `time5.apple.com`

#### `time6.apple.com`

#### `time7.apple.com`

### [微软 Windows](https://docs.microsoft.com/zh-cn/windows-server/networking/windows-time-service/how-the-windows-time-service-works#windows-time-service-time-protocols)

#### `time.windows.com`

### [美国标准技术研究院](https://tf.nist.gov/tf-cgi/servers.cgi)

#### `time.nist.gov`


# MAC 地址厂商信息

总算能理解 IPv6 里的 EUI-64 咋来的了

## 引言

在手头用的无线路由器的后台，有这么一个设置：

![终端品牌识别](/files/Phz1xHtkhQ34g0s6ScHd)

这个倒也好理解，应该就是会从服务器下载 MAC 地址对应的厂商数据库。然后就可以根据 MAC 地址对设备的品牌进行识别，并在显示时加上对应的 LOGO，方便用户直观地分辨联网设备。

最近在处理校园网络答疑解惑的工作时，发现无线网络认证的日志中，与联网设备相关的只有一个干干的 MAC 地址，实在是不便于区分具体的设备（总不能指望用户给你报 MAC 地址吧）。联想到路由器上的这个功能，打算扩展一下日志内容，利用 MAC 地址对设备厂商进行标注。

**搜集资料过程中发现** [**IEEE 官网**](https://standards.ieee.org) 的**官方资料与互联网上的内容出入较大，故做以记录。**

## 常见资料的问题

> MAC 地址共 48 位（6 个字节），以十六进制表示。第 1 Bit 为广播地址（0）/群播地址（1），第 2 Bit 为广域地址（0）/区域地址（1）。前 3-24 位由 IEEE 决定如何分配给每一家制造商，且不重复，后 24 位由实际生产该网络设备的厂商自行指定且不重复。

**以上这种说法其实有点管中窥豹的感觉，并不全面。**

IEEE 分配给制造商的其实是 OUI，其长度除了最常见的 24 位，还可能是 28 位或者 36 位。而 48 位 MAC 地址，属于 IEEE 标准中的 EUI，是由 OUI 扩展而来的。也就是说为了识别制造商，需要匹配的位数可能不止 24 位。

{% hint style="info" %}
这一点其实本质上与 [无类别域间路由](https://zh.wikipedia.org/wiki/%E6%97%A0%E7%B1%BB%E5%88%AB%E5%9F%9F%E9%97%B4%E8%B7%AF%E7%94%B1) Classless Inter-Domain Routing 非常接近，都是对地址的分层进行细化，以提高利用率。
{% endhint %}

## 官方资料

### 标识符概念的解释

{% file src="/files/-MhwjHmYkWWwyQ\_Md0SE" %}
Guidelines for Use of Extended Unique Identifier (EUI), Organizationally Unique Identifier (OUI), and Company ID (CID)
{% endfile %}

### 查询标识符的页面

{% embed url="<https://regauth.standards.ieee.org/standards-ra-web/pub/view.html>" %}

### 标识符数据文件

1. MAC Address Block Large (**MA-L**) [TXT](http://standards-oui.ieee.org/oui/oui.txt) [CSV](http://standards-oui.ieee.org/oui/oui.csv)
2. MAC Address Block Medium (**MA-M**) [TXT](http://standards-oui.ieee.org/oui28/mam.txt) [CSV](http://standards-oui.ieee.org/oui28/mam.csv)
3. MAC Address Block Small (**MA-S**) [TXT](http://standards-oui.ieee.org/oui36/oui36.txt) [CSV](http://standards-oui.ieee.org/oui36/oui36.csv)

## 重点内容

### 术语缩写

* **CUI**: Company ID 公司标识符
* **OUI**: Organizationally Unique Identifier 组织唯一标识符
* **EUI**: Extended Unique Identifiers 扩展统一标识符
* **MAC**: Media Access Control (Address) 媒体访问控制（地址）
* **RA**: Registration Authority 注册机构

{% hint style="info" %}
`XXX-N` 代表长度为 N 个二进制位的 XXX 类型的标识符。
{% endhint %}

### 对应关系

|    标识符 | 常见用途                 |
| -----: | -------------------- |
| EUI-48 | MAC-48（通常所说的 MAC 地址） |
| EUI-64 | MAC-64（仍未广泛应用）       |

> EUI-48 和 EUI-64 标识符最普遍的用法是作为全球唯一的网络地址（有时称为 MAC 地址），如各种标准中规定的那样。例如，根据 IEEE 标准 802，EUI-48 通常被用作硬件接口的地址，历史上使用 "MAC-48"的名称。另一个例子是，根据 IEEE 标准 1588，EUI-64 可作为一个时钟的标识符。IEEE 标准 802 还规定了 EUI-64 用于 64 位全球唯一的网络地址。
>
> > EUI-48 and EUI-64 identifiers are most commonly used as globally unique network addresses (sometimes called MAC addresses), as specified in various standards. For example, an EUI- 48 is commonly used as the address of a hardware interface according to IEEE Std 802, historically using the name “MAC-48”. As another example, an EUI- 64 may serve as the identifier of a clock, per IEEE Std 1588. IEEE Std 802 also specifies EUI-64 use for 64-bit globally unique network addresses.

### MAC 地址注册类型

* **MA-L**: MAC-Large 大块的 MAC 地址
* **MA-M**: MAC-Middle 中块的 MAC 地址
* **MA-S**: MAC-Small 小块的 MAC 地址

![EUI, OUI, and CID assignment summary](/files/-MhxqNSsGz2i4C7x4H2X)

### EUI-48 的结构

![Structure of EUI-48](/files/-MhwljgD7iTMZveLFjEp)

## 如何根据 EUI-48 匹配 OUI

> 如果前 24 位与分配给 IEEE RA 的 OUI 相匹配，那么对前 28 位或 36 位的搜索可能会显示出 MA-M 或 MA-S 的分配。\
> 如果在 MA-S 搜索中没有发现 OUI-36，那么对前 24 位或 28 位的搜索可能会发现一个 MA-L 或 MA-M 分配，OUI-36 是由分配块的一个成员创建的。
>
> > If the first 24 bits match an OUI assigned to the IEEE RA, then a search of the first 28 or 36 bits may reveal an MA-M or MA-S assignment. If the OUI-36 is not found in an MA-S search, then a search of the first 24 or 28 bits may reveal an MA-L or MA-M assignment from which the OUI-36 has been created from a member of the assigned block.

{% hint style="warning" %}
最终的查询结果也不总是完全准确的哦！

> 请您注意，所列的公司和编号在产品实施中可能并不总是很明显。一些制造商将部件制造分包出去，另一些制造商在其产品中包括注册公司的所有 MAC（MA-L、MA-M、MA-S）。
>
> > Your attention is called to the fact that the firms and numbers listed may not always be obvious in product implementation. Some manufacturers subcontract component manufacture and others include registered firms' All MAC (MA-L, MA-M, MA-S) in their products.
> > {% endhint %}

具体的步骤如下：

1. 取 MAC 地址前 **24** 位（对应到常用的杠分十六进制表示就是前三组的 6 个 十六进制字符，如 AA-BB-CC-DD-EE-FF 的 AABBCC）\
   与数据库的 `assignment` 字段进行精确匹配。
2. 若匹配结果的 `organization_name` 字段为 `IEEE Registration Authority` ，则继续进行下一步；\
   否则直接返回当前匹配结果。
3. 取 MAC 地址前 **28** 位（对应到常用的杠分十六进制表示就是前三组的 7 个 十六进制字符，如 AA-BB-CC-DD-EE-FF 的 AABBCCD）\
   与数据库的 `assignment` 字段进行精确匹配。
4. 若匹配结果的 `organization_name` 字段为 `IEEE Registration Authority` ，则继续进行下一步；否则直接返回当前匹配结果。
5. 取 MAC 地址前 **36** 位（对应到常用的杠分十六进制表示就是前三组的 7 个 十六进制字符，如 AA-BB-CC-DD-EE-FF 的 AABBCCD）\
   与数据库的 `assignment` 字段进行精确匹配。
6. 若有结果直接返回，无结果返回空。


# 点对点的中介

PPPoE Relay 原理解析

某可爱四年内第 N 次提及 PPPoE-Relay 的原理，终于让我的好奇心冲破了发际线。

是时候狠心读一波 RFC 终结这个话题了！

## 了解 PPP 和 Ethernet

### PPP (Point-to-Point Protocol)

1. 用于点对点通信的通用协议。
2. 设计为工作在网络层（常见的 IP 协议）之下。
3. 采用 C/S 架构。
4. 内含 **Link Control Protocol**，提供身份验证功能。
5. 内含 **Network Control Protocol**，可完成对网络层（IP）的基础配置。

### **Ethernet**

1. 以太网，常见的链路层协议。
2. 平常说的 MAC 地址就是该协议的一部分。

## 了解 PPPoE

### PPPoE (PPP Over Ethernet)

1. 工作在以太网之上的 PPP。
2. 继承了 PPP 的所有功能
3. 在 ADSL 时代就普遍使用，当时被冠以 *拨号连接* 之名，沿用至今。

> 以太网数据包【PPPoE 数据包（IP 数据包）】

### 为何 ISP 独爱 PPPoE

1. 点对点连接一定程度上提升了用户网络的安全性（例如不使用 ARP，从根本上防御了 ARP 攻击）。
2. 便于计时计量，结合身份验证可完成计费。
3. 可以完成网络层配置的任务（不再需要 DHCP）。

### PPP 如何 oE？

PPP 协议建立在客户端与服务器能够稳定双工通信的前提下。

就以太网而言，这需要客户端与服务端互相知晓对方的 MAC 地址，所以在 PPP 协议之前额外增加了 **Discovery Stage** 过程，在此过程中有以下 5 种数据包：

1. The PPPoE Active Discovery Initiation (PADI) packet\
   客户端向本地以太网域广播该包。
2. The PPPoE Active Discovery Offer (PADO) packet\
   服务器向客户端单播回应，可能存在多个服务器，故此时客户端可能收到多个包。
3. The PPPoE Active Discovery Request (PADR) packet\
   客户端选择一个服务器，单播发送该包，请求会话。
4. The PPPoE Active Discovery Session-confirmation (PADS) packet\
   服务器向客户端单播回应，确认会话开始。
5. The PPPoE Active Discovery Terminate (PADT) packet\
   客户端和服务器均可单播发送该包，终止会话。

## PPPoE Relay

### 功能

让处于不同以太网域（如被路由器隔离的 WAN 侧和 LAN 侧）中的客户端和服务器也能够建立 PPPoE 会话。

### 场景

运营商提供给你一个以太网接入方式（光猫桥接），你首先把路由器 WAN 口与运营商网络连接，用路由器拨号，而后又将电脑连接到路由器的 LAN 口。

没有其他设置时，电脑（客户端）启动 PPPoE 后，进入 Discovery Stage，发送的 PADI 数据包只能在 LAN 域中广播，无法到达运营商位于 WAN 域中的服务器。

{% hint style="info" %}
路由器作为网络层设备，它将划分 WAN 和 LAN 两个链路层域（以太网域）。
{% endhint %}

在路由器启用 PPPoE Relay 后，它会探测并识别 Discovery Stage 产生的数据包，并进行特定的标记处理和转发，保证客户端和服务器之间能够正常收发数据。此时电脑（客户端）可以与服务端完成 Discovery Stage 并开始下一阶段的 PPP 协议。

{% hint style="warning" %}
PPP 协议比较复杂，要经历 参数协商 -> 身份认证 -> 网络层配置 三个主要阶段。\
PPPoE Relay 只保证 PPP 协议能够运行，但若是出现身份认证不通过、网络配置冲突等问题，最终还是会导致整个 PPPoE 失败。
{% endhint %}

### 原理

侦测并处理 Discovery Stage 阶段的 5 类数据包，具体处理如下。

后文将 PPPoE Relay 称为 **中继**。

#### PADI

中继在 PPPoE 数据包中添加 `Relay-Session-ID` 标记用于追踪对话。这个标记是 RFC 中规定的，客户端和服务器若收到了带有这个标记的数据包，它们必须在响应中也包含相同的标记：

> 0x0110 Relay-Session-Id
>
> This TAG MAY be added to any discovery packet by an intermediate agent that is relaying traffic. The TAG\_VALUE is opaque to both the Host and the Access Concentrator. If either the Host or Access Concentrator receives this TAG they MUST include it unmodified in any discovery packet they send as a response. All PADI packets MUST guarantee sufficient room for the addition of a Relay-Session-Id TAG with a TAG\_VALUE length of 12 octets.
>
> A Relay-Session-Id TAG MUST NOT be added if the discovery packet already contains one. In that case the intermediate agent SHOULD use the existing Relay-Session-Id TAG. If it can not use the existing TAG or there is insufficient room to add a Relay- Session-Id TAG, then it SHOULD return a Generic-Error TAG to the sender.

在添加标记后，中继会将 PADI 数据包广播到服务器所在的以太网域（一般是 WAN）。

#### PADO

中继检查 PADO 中的 Relay-Session-ID，并据此转发给对应的客户端。

#### PADR

类似于对 PADI 的处理。

#### PADS

当接收到 PADS 时，中继将两个对等方的 MAC 地址和会话 ID 输入到哈希表中。（访问集中器看到的会话 ID 可能与客户端看到的不同；中继必须重新编号会话以避免重复会话 ID 的可能性。）每当任何对等方发送会话帧时，中继都会查找哈希表中的会话条目，并将帧中继到正确的对等方。

#### PADT

当接收到 PADT 时，中继将其转发到对等方并从其哈希表中删除会话条目。

## 参考源

1. [RFC 2516 - A Method for Transmitting PPP Over Ethernet (PPPoE)](https://datatracker.ietf.org/doc/html/rfc2516)
2. [pppoe-relay(8) - Linux man page](https://linux.die.net/man/8/pppoe-relay)
3. [10 张图带你搞懂数据链路层 PPP 点到点协议](https://zhuanlan.zhihu.com/p/153515394)


# Windows 使用小技巧

## 快捷键

{% hint style="info" %}
Windows 的前身 **MS-DOS** 原生是不支持鼠标的哦！所以硬要追根溯源的话，**键盘才是 Windows 最正统的操作方式** 。
{% endhint %}

![](/files/-MgE1g9RFrxiW4VL_MeV)

### 系统快捷键

{% hint style="info" %}
**Windows 徽标键（亦称作 WIN 键）** 可以与下面图示中的键组合
{% endhint %}

![Powertoys 快捷键指南](/files/-MgDynwT3cau83St3YhS)

{% hint style="info" %}
**`ALT + TAB` 切换窗口**
{% endhint %}

{% hint style="info" %}
**`CTRL + SHIFT + ESC 任务管理器`**
{% endhint %}

{% hint style="danger" %}
**`CTRL + SHIFT + DELETE` 应急设置**\
也被称作“**三指敬礼**” （Three-finger Salute）向\_比尔·盖茨\_和“**安全键**” （Security Keys）
{% endhint %}

### 通用快捷键

|                基础键 |    指令键    | 命令      |
| -----------------: | :-------: | ------- |
|         **`CTRL`** |  **`S`**  | **保存**  |
|         **`CTRL`** |  **`C`**  | **复制**  |
|         **`CTRL`** |  **`V`**  | **粘贴**  |
|         **`CTRL`** |  **`F`**  | **查找**  |
|         **`CTRL`** |  **`P`**  | **打印**  |
|         **`CTRL`** | **`TAB`** | **切换**  |
|          **`ALT`** |  **`F4`** | **关闭**  |
| **`CTRL + SHIFT`** |  **`S`**  | **另存为** |

## 控制面板

**`控制面板`** 集成了 Windows 系统相关的绝大多数功能与配置选项。\
尽管自 Windows 8 以来微软就致力于用新的 **`设置`** 页面来替代传统的控制面板，但这一项目推进缓慢，同时新的页面布局并未得到广泛认可（个人就觉得控制面板更直观、页面利用率更高）。哪怕是到了 Windows 11，依旧有很多设置项缺失，所以遇到需要调整复杂设置的情况还是得靠\*\*`控制面板`\*\*。

{% hint style="info" %}
**`WIN + R`** 打开 **运行** 窗口，输入对应的控制面板文件名，回车，即可快速打开窗口。
{% endhint %}

|          文件名 | 对应窗口        |
| -----------: | ----------- |
|      control | 控制面板        |
|   appwiz.cpl | 程序和功能       |
|     desk.cpl | 显示设置        |
|  inetcpl.cpl | Internet 属性 |
|     intl.cpl | 区域设置        |
|      joy.cpl | 游戏控制器       |
|     main.cpl | 鼠标属性        |
|    mmsys.cpl | 声音          |
|     ncpa.cpl | 网络连接        |
| powercfg.cpl | 电源选项        |
|    sysdm.cpl | 系统属性        |
| tabletpc.cpl | 笔和触控        |
| timedate.cpl | 日期和时间       |
|     netplwiz | 用户账户        |

{% hint style="warning" %}
尽管在微软的 [官方文档](https://support.microsoft.com/en-us/topic/description-of-control-panel-cpl-files-4dc809cd-5063-6c6d-3bee-d3f18b2e0176) 中有提及对应的控制面板文件名，但此文档已经长期未经维护，不再适用于 Windows 7 之后的版本。\
以上的内容汇总了官方文档和注册表中的内容，筛选了其中的有效项，还增加了部分不是控制面板项但与之相关的程序。

相关的注册表键：\
`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cpls`
{% endhint %}

## 系统修复

首先用 **部署映像服务和管理（Deployment Image Servicing and Management）** 确保 wim 文件的完好。

```powershell
DISM.exe /Online /Cleanup-image /Restorehealth
```

接下来用 **系统文件检查器（System File Checker）** 根据 wim 文件为准对现有的系统文件进行检查和修复。

```powershell
SFC /SCANNOW
```


# SSH 技高一筹

SSH 使用小技巧

> Linux 不能失去 SSH，就像西方不能失去耶路撒冷。  ——WH-2099

Linux 用户免不了接触 SSH，但大多数人还停留&#x5728;**“会用，能用”**&#x7684;水平，本文从三个方面入手

## 配置提升

### 服务端

### 客户端

## 身份验证

### 部署证书体系

SSH 常见的身份验证方式有 3 种，根据其安全性自弱向强排列：

1. 密码验证
2. 公钥验证
3. 证书验证

选用证书验证，能够更加

### 公钥加密算法选用 ED25519

#### 原因

个人对加密算法了解很浅薄，所以只能参考网络上的各类资料，例如 [Comparing SSH Keys - RSA, DSA, ECDSA, or EdDSA?](https://goteleport.com/blog/comparing-ssh-keys/) 。

在安全应用领域里（如 tls 证书），用 ED25519 替换 RSA 正成为主流。

就实际使用而言，ED25519 生成的密钥很短，没条件复制粘贴的时候，手敲也不会太痛苦。

#### 方法

```
ssh-keygen -t ed25519
```

## 隧道转发

### 本地转发

### 动态转发

## 参考源

1. [ssh(1)](https://man.archlinux.org/man/ssh.1.en)
2. sshd(8)
3. ssh-agent(1)


# ZFS 默认参数还不够好

ZFS 存储池创建最佳实践

在构建现代 NAS、海量数据存储或高性能虚拟化宿主机时，ZFS 是目前最强大的文件系统之一。然而，ZFS 的默认配置偏向于传统的 Unix 环境，直接使用默认命令建池往往无法发挥其在 Linux 下的最大潜力。

### 第一部分：创建命令

假设我们拥有 4 块硬盘，准备组建容错率为 2 块盘的 **RAIDZ2** 阵列：

#### 步骤 1：创建根池

<pre class="language-bash"><code class="lang-bash">sudo zpool create -o ashift=12 \
    -o compatibility=off \
    -O normalization=formC \
<strong>    -O compression=zstd \
</strong>    -O atime=off \
    -O xattr=sa \
    -O dnodesize=auto \
    -O acltype=posix \
    -O canmount=off \
    tank raidz2 \
    /dev/disk/by-id/ata-WD_RED_1... \
    /dev/disk/by-id/ata-WD_RED_2... \
    /dev/disk/by-id/ata-WD_RED_3... \
    /dev/disk/by-id/ata-WD_RED_4...
</code></pre>

#### 步骤 2：创建数据集

```bash
sudo zfs create tank/data
```

执行完毕后，你的数据就可以安全地存入 `/tank/data` 目录了。

### 第二部分：为什么叫 `tank`？

在几乎所有的 ZFS 官方文档和教程中，存储池的名字总是叫 `tank`：

1. **核心隐喻（水池与水箱）**：ZFS 的核心创新是抛弃了死板的分区，提出了“存储池（Storage Pool）”的概念。所有的底层硬盘汇聚成一汪可以流动的“水”（容量）。既然是 Pool（池子），那用来装载这些数据水流的容器，自然就是 Tank（水箱）。
2. **《黑客帝国》的终极彩蛋**：ZFS 诞生于 2001 年的 Sun 公司。当时电影《黑客帝国》（The Matrix）风靡硅谷。在电影中，主角飞船上那位**负责管理所有数据流、加载虚拟环境程序的操作员**，名字就叫 **Tank**。在当年早期的 ZFS 测试代码中，甚至还出现了 `dozer`（Tank 的哥哥）、`neo`（男主角）和 `zion`（人类家园）等命名。
3. **极简主义**：`tank` 只有四个字母，全部在键盘左手区，没有任何数字，敲击极快，且在 Linux 枯燥的命名（如 `vg0`, `md127`）中极具辨识度。

### 第三部分：配置解析

#### 1. 建池规则

* **使用硬盘 ID (`/dev/disk/by-id/...`)**
  * Linux 重启时，`/dev/sda`、`/dev/sdb` 这样的盘符可能会发生漂移变化。使用全球唯一的硬盘物理 ID 建池，可以保证无论硬盘插在哪个接口，ZFS 都能准确无误地识别并导入阵列。
* **`-o ashift=12`（建池后不可更改！）**
  * `ashift` 决定了底层最小写入扇区大小（2^12 = 4096）。现代硬盘即使物理扇区是 4K，为了兼容老系统，也会向操作系统“谎称”自己是 512 字节。如果不强制设为 `12`，ZFS 会信以为真，导致每次写入都需要进行极度消耗性能的“读-改-写”操作。强制 `ashift=12` 可消除这种写放大，保护性能和硬盘寿命。注意这里是小写的 `-o`，代表 Pool 级别的底层属性。
* **`-o compatibility=off`**
  * 关闭功能兼容模式，这意味着该存储池将启用当前 ZFS 版本支持的所有最新特性（Features）。这在不需要将该存储池导入到旧版本 ZFS 或其他操作系统（如旧版 FreeBSD/Solaris）时是最好的选择。

#### 2. 空间与性能

* **`-O normalization=formC`**
  * 开启 Unicode 字符归一化，这可以确保不同操作系统（如 Windows、macOS 和 Linux）通过 SMB/NFS 等网络协议访问时，文件名中的特殊字符（特别是带声调或组合符号的语言）不会出现乱码或找不到文件的问题。
* **`-O compression=zstd`（透明压缩）**
  * Zstandard 是目前最优秀的压缩算法。开启后，不仅凭空增加大量可用空间（文本、日志、虚拟磁盘等压缩率极高），而且由于写入物理硬盘的数据变少了，反而能**提升整体的 I/O 吞吐速度**。
* **`-O atime=off`（关闭访问时间）**
  * Linux 默认会在你每次“读取”文件时，向硬盘发起一次“写入”操作来更新访问时间。关闭它，让读取操作变成纯粹的只读，消除大量无谓的碎片化写入，大幅提升读取速度。

#### 3. 小文件优化

在 Linux 下运行 ZFS（尤其是提供 SMB 共享或存储大量小文件时），以下三个参数必须绑定开启：

* **`-O xattr=sa`（扩展属性存入系统属性）**
  * Linux 的扩展属性（如 SELinux 标签、Samba 权限）默认会被 ZFS 写在隐藏的独立目录中，导致每次读取都需要额外的磁盘寻道。设为 `sa` 后，这些属性会直接写在文件的 inode（dnode）内部，性能呈指数级提升。
* **`-O dnodesize=auto`（动态节点大小）**
  * 传统的 dnode 大小固定为 512 字节，如果复杂的权限属性塞不下，依然会导致性能下降。设为 `auto` 允许 ZFS 动态分配更大的 dnode 来一口气装下所有元数据。
* **`-O acltype=posix`（POSIX 访问控制列表）**
  * 启用高级权限控制。如果你需要为不同的用户组分配精细的权限，或者无缝对接 Windows 的 Samba 共享权限映射，这是必选项。

#### 4. 拓扑设计

* **`-O canmount=off`（禁止挂载根节点）**
  * 这是最高级的设计模式。我们在 `tank` 上打满了各种优化配置，但禁止挂载 `tank` 本身。此时，`tank` 变成了一个纯粹的“属性模板（Container/Template）”。
  * 随后我们通过 `zfs create tank/data` 创建子数据集时，`tank/data` 会**自动继承** `tank` 的所有优化属性（除了 `canmount` 会恢复正常挂载）。这保证了数据绝对不会意外写进根目录，且未来可以轻松地创建拥有不同特性的平行数据集（例如单独建一个 `tank/vm` 并将块大小 `recordsize` 改为 64K 专门放虚拟机），实现互不干扰、干净清爽的存储拓扑。


# nftables 速成

功能确实很强大，但这也太复杂了

## 简介

> Nftables 是现代 Linux 内核数据包分类框架。新的代码应该使用它来代替遗留的 `{ip, ip6, arp, eb}_tables (xtables)` 基础设施。对于尚未转换的现有代码库，遗留的 xtables 基础设施将维护到到 2021 年。

在 Linux 服务器的日常维护中，网络防火墙是很重要的一环。对于一般用途而言，其实需要的防火墙策略都不是很复杂，没有必要为此而购买独立的软硬件防火墙，使用 Linux 内嵌的基础网络包处理就完全足够应对。

iptables 作为这方面的老大哥，在 Linux 系统的基础网络包处理一线坚挺了多年。但随着时代的发展，老大哥也到了该退休的岁数，目前公认的继任者就是 nftables。

相较于 iptables，nftables 的框架设计更为合理，功能更为全面，命令行的语法也更为清晰。但从网络上关于 nftables 的资料并不多这一点就不难看出，nftables 目前的应用仍不是非常广泛。（和 IPv6 同病相怜）这主要是因为 nftables 丰富的功能和特性立足于陡峭的学习曲线之上，令用户望而却步。

{% hint style="info" %}
关于 nftables 的具体简介可以参照这里 [What is nftables?](https://wiki.nftables.org/wiki-nftables/index.php/What_is_nftables%3F)
{% endhint %}

## 命令

```
nft 选项 动作 对象
```

### 动作

```
基础动作 动作目标
```

#### 选项

* `-n, --numeric` 打印完整的数字输出
* `-c, --check` 检查命令的有效性，而不实际应用更改
* `-a, --handle` 在输出中显示对象句柄
* `-e, --echo` 当使用 `add`，`insert` 或 `replace` 命令将项目插入到规则集时，就像 `nft monitor` 一样打印通知
* `-I, --includepath directory` 在要搜索包含的文件目录列表中添加 *directory*。这个选项可以被多次指定
* `-f, --file filename` 从 *filename* 读取输入。如果 *filename* 是 `-`，则从 stdin 读取
* `-i, --interactive` 从一个交互式的 readline CLI 中读取输入。你可以使用 `quit` 来退出，或者使用 EOF 标记，通常是 `CTRL-D`

#### 基础动作

* **`list`** 查看
* **`create`** 创建
* **`add`** 添加
* **`insert`** 插入
* **`replace`** 替换
* **`delete`** 删除
* **`flush`** 清空

{% hint style="info" %}
`add` 和 `create` 的唯一区别是，如果指定的内容已经存在，`add` 不会返回错误，而 `create` 会返回错误。
{% endhint %}

#### 动作目标

* **`ruleset`**
* **`table`**
* **`chain`**
* **`rule`**
* **`set`**
* **`map`**
* **`element`**

{% hint style="info" %}
动作目标与对象是对应关系。
{% endhint %}

## 对象

### Address Family 地址族

地址族决定处理的数据包的类型。对于每个地址族，内核在数据包处理路径的特定阶段包含所谓的钩子，如果存在这些钩子的规则，这些钩子将调用 nftables。

* **`ip`** IPv4，**默认**
* **`ip6`** IPv6
* **`inet`** Internet （IPv4/IPv6）
* **`arp`** 处理 IPv4 ARP 数据包
* **`bridge`** 处理通过网桥设备的数据包
* **`netdev`** 处理来自入口的数据包

###

### Ruleset 规则集

`ruleset` 关键字用于标识内核中当前到位的整个表、链等集合。

```
{list | flush} ruleset [family]
```

### Tables 表

表是链、集和有状态对象的容器，通过地址族家庭和名称来识别。

```
{add | create} table [family] table [{ flags flags ; }]
{delete | list | flush} table [family] table
list tables [family]
delete table [family] handle handle
```

### Chain 链

链条是规则的容器，分为基链和规则链两种。

```
{add | create} chain [family] table chain [{ type type hook hook [device device] priority priority ; [policy policy ;] }]
{delete | list | flush} chain [family] table chain
list chains [family]
delete chain [family] table handle handle
rename chain [family] table chain newname
```

#### **基本链**

基本链是网络堆栈中数据包的入口点，必须包含类型、钩子和优先级参数。

**类型**

* `filter` 过滤时使用的标准类型。
* `nat` 基于连接跟踪条目执行地址转换。只有连接的第一个数据包实际穿越该链——其规则通常定义所创建的连接跟踪条目的细节（例如 NAT 语句）。
* `route` 如果一个数据包已经穿越了这种类型的链，并且即将被接受，如果 IP 头的相关部分发生了变化，就会进行新的路由查询。这允许在 nftables 中实现策略路由选择器。

**钩子**

* `prerouting` 刚到达并未被 nftables 的其他部分所路由或处理的数据包。
* `input` 已经被接收并且已经经过 `prerouting` 钩子的传入数据包。
* `forward` 如果数据报将被发送到另一个设备，它将会通过 `forward` 钩子。
* `output` 从本地传出的数据包。
* `postrouting` 仅仅在离开系统之前，可以对数据包进行进一步处理。

**优先级**

优先级参数接受一个带符号的整数值或一个标准的优先级名称，该名称指定具有相同钩子值的链的遍历顺序。排序是升序的，也就是说低优先级的值优先于高优先级的值。标准的优先级值可以用容易记忆的名称替换。并不是所有的名字在每个钩子族中都有意义 (参见 [钩子可用性](#gou-zi-ke-yong-xing)) ，但是它们的数值仍然可以用来排列链的优先级。

* `raw`
* `mangle`
* `dstnat`
* `filter`
* `security`
* `srcnat`

#### 规则链

规则链可以作为跳转目标，用于更好地组织规则。

### Rule 规则

规则是根据一套语法规则由两类成分构成的：表达式和声明。

```
{add | insert} rule [family] table chain [handle handle | index index] statement ... [comment comment]
replace rule [family] table chain handle handle statement ... [comment comment]
delete rule [family] table chain handle handle
```

{% hint style="warning" %}
规则内容过于冗杂，建议直接阅读 [Quick reference-nftables in 10 minutes](https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes)
{% endhint %}

## 输入文件

* `\` 如果上一行的最后一个字符是非引号反斜杠，则下一行被视为延续
* `;` 将同一行中的多个命令分开
* `#` 后面的同一行字符都被忽略
* `include filename` 包含 *filename* 文件的内容
* `define variable = expr` 定义值为 *expr* 的变量 *variable*
* `$variable` 引用变量 *variable* 的值

{% hint style="info" %}
标识符以字母字符 `[a-zA-Z]` 开头，后面跟着零个或多个字母数字字符 `[a-zA-Z0-9]` 和字符斜杠 `[/]` 、反斜杠 `[\\]`、下划线 `[_]` 和点 `[\.]` 。使用不同字符或与关键字冲突的标识符需要用双引号 `["]` 括起来。
{% endhint %}

## 通用容器

### Set 集合

nftables 提供了两种集合概念：匿名集和命名集。

#### 匿名集

匿名集是没有特定名称的集合。集合成员用花括号括起来，在创建集合使用的规则时，用逗号分隔元素。一旦该规则被删除，集合也会被删除。它们不能被更新，也就是说，一旦一个匿名集被声明，它就不能再被更改，除非删除/更改使用匿名集的规则。

#### 命名集

```
add set [family] table set { type type | typeof expression ; [flags flags ;] [timeout timeout ;] [gc-interval gc-interval ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] [auto-merge ;] }
{delete | list | flush} set [family] table set
list sets [family]
delete set [family] table handle handle
{add | delete} element [family] table set { element[, ...] }
```

| **Keyword** | **Description**                         | **Type**                                                                      |
| ----------- | --------------------------------------- | ----------------------------------------------------------------------------- |
| type        | 集合中元素的数据类型                              | string: ipv4\_addr, ipv6\_addr, ether\_addr, inet\_proto, inet\_service, mark |
| typeof      | 集合中元素的数据类型                              | 要用于获取类型的表达式                                                                   |
| flags       | 设置标志                                    | string: constant, dynamic, interval, timeout                                  |
| timeout     | 一个元素停留在集合中的时间，如果集合被添加到数据包路径（规则集），则是强制性的 | string, decimal followed by unit. Units are: d, h, m, s                       |
| gc-interval |                                         |                                                                               |
|             |                                         |                                                                               |
|             | 垃圾收集时间间隔，只有在超时或标志超时激活时才可用               | string, decimal followed by unit. Units are: d, h, m, s                       |
| elements    | 集合包含的元素                                 | 集合的数据类型                                                                       |
| size        | 集合中的最大元素数，如果集合是由数据包路径（规则集）添加的，则是强制性的    | unsigned integer (64 bit)                                                     |
| policy      | 设置策略                                    | string: performance \[default], memory                                        |
| auto-merge  | 自动合并相邻/重叠的集合元素（仅适用于区间集合）                |                                                                               |

### Map 映射

映射根据用作输入的某个特定键存储数据。它们由用户定义的名称唯一标识并附加到表中。

```
add map [family] table map { type type | typeof expression [flags flags ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] }
{delete | list | flush} map [family] table map
list maps [family]
```

| Keyword  | Description | Type                                                                                                        |
| -------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
| type     | 映射中元素的数据类型  | string: ipv4\_addr, ipv6\_addr, ether\_addr, inet\_proto, inet\_service, mark, counter, quota 计数器和配额不能作为键使用 |
| typeof   | 映射中元素的数据类型  | 要用于获取类型的表达式                                                                                                 |
| flags    | 设置标志        | string: constant, interval                                                                                  |
| elements | 映射包含的元素     | 映射的数据类型                                                                                                     |
| size     | 映射中元素的最大数量  | string: performance \[default], memory                                                                      |
| policy   | 映射策略        | string: performance \[default], memory                                                                      |

### Element 元素

与元素相关的命令允许更改命名集和映射的内容。

```
{add | create | delete | get } element [family] table set { ELEMENT[, ...] }

ELEMENT := key_expression OPTIONS [: value_expression]
OPTIONS := [timeout TIMESPEC] [expires TIMESPEC] [comment string]
TIMESPEC := [numd][numh][numm][num[s]]
```

| **Option** | **Description**     |
| ---------- | ------------------- |
| timeout    | 带有超时标志的集合/映射的超时值    |
| expires    | 给定元素过期的时间，仅对规则集复制有用 |
| comment    | 每个元素的注释字段           |

## 参考图表

#### 钩子触发流程

![](/files/-Mhh14r_9WcY_jv_mZoT)

#### 钩子可用性

{% hint style="warning" %}
白名单列举，没有明确标为 Yes 的都不可用。
{% endhint %}

| Chain type                                | ingress | prerouting | forward | input | output | postrouting |  egress  |
| ----------------------------------------- | :-----: | :--------: | :-----: | :---: | :----: | :---------: | :------: |
| **inet family**                           |         |            |         |       |        |             |          |
| filter                                    |   Yes   |     Yes    |   Yes   |  Yes  |   Yes  |     Yes     |          |
| nat                                       |         |     Yes    |         |  Yes  |   Yes  |     Yes     |          |
| route                                     |         |            |         |       |   Yes  |             |          |
| <p><br><strong>ip6 family</strong></p>    |         |            |         |       |        |             |          |
| filter                                    |         |     Yes    |   Yes   |  Yes  |   Yes  |     Yes     |          |
| nat                                       |         |     Yes    |         |  Yes  |   Yes  |     Yes     |          |
| route                                     |         |            |         |       |   Yes  |             |          |
| <p><br><strong>ip family</strong></p>     |         |            |         |       |        |             |          |
| filter                                    |         |     Yes    |   Yes   |  Yes  |   Yes  |     Yes     |          |
| nat                                       |         |     Yes    |         |  Yes  |   Yes  |     Yes     |          |
| route                                     |         |            |         |       |   Yes  |             |          |
| <p><br><strong>arp family</strong></p>    |         |            |         |       |        |             |          |
| filter                                    |         |            |         |  Yes  |   Yes  |             |          |
| <p><br><strong>bridge family</strong></p> |         |            |         |       |        |             |          |
| filter                                    |         |     Yes    |   Yes   |  Yes  |   Yes  |     Yes     |          |
| <p><br><strong>netdev family</strong></p> |         |            |         |       |        |             |          |
| filter                                    |   Yes   |            |         |       |        |             | Yes(5.7) |

#### 钩内优先级

{% hint style="info" %}
在给定的钩子中，会按照数字递增的顺序执行操作，所以 **数字越小优先级越高** 。
{% endhint %}

| nftables [Families](https://wiki.nftables.org/wiki-nftables/index.php/Nftables_families) | Typical hooks      | nft Keyword  | Value    | Netfilter Internal Priority      | Description                                                                                                                                                                                           |
| ---------------------------------------------------------------------------------------- | ------------------ | ------------ | -------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|                                                                                          | prerouting         |              | -450     | NF\_IP\_PRI\_RAW\_BEFORE\_DEFRAG |                                                                                                                                                                                                       |
| inet, ip, ip6                                                                            | prerouting         |              | -400     | NF\_IP\_PRI\_CONNTRACK\_DEFRAG   | Packet defragmentation / datagram reassembly                                                                                                                                                          |
| inet, ip, ip6                                                                            | all                | **raw**      | -300     | NF\_IP\_PRI\_RAW                 | Traditional priority of the raw table placed before connection tracking operation                                                                                                                     |
|                                                                                          |                    |              | -225     | NF\_IP\_PRI\_SELINUX\_FIRST      | SELinux operations                                                                                                                                                                                    |
| inet, ip, ip6                                                                            | prerouting, output |              | -200     | NF\_IP\_PRI\_CONNTRACK           | [Connection tracking](https://wiki.nftables.org/wiki-nftables/index.php/Connection_Tracking_System) processes run early in prerouting and output hooks to associate packets with tracked connections. |
| inet, ip, ip6                                                                            | all                | **mangle**   | -150     | NF\_IP\_PRI\_MANGLE              | Mangle operation                                                                                                                                                                                      |
| inet, ip, ip6                                                                            | prerouting         | **dstnat**   | -100     | NF\_IP\_PRI\_NAT\_DST            | Destination NAT                                                                                                                                                                                       |
| inet, ip, ip6, arp, netdev                                                               | all                | **filter**   | 0        | NF\_IP\_PRI\_FILTER              | Filtering operation, the filter table                                                                                                                                                                 |
| inet, ip, ip6                                                                            | all                | **security** | 50       | NF\_IP\_PRI\_SECURITY            | Place of security table, where secmark can be set for example                                                                                                                                         |
| inet, ip, ip6                                                                            | postrouting        | **srcnat**   | 100      | NF\_IP\_PRI\_NAT\_SRC            | Source NAT                                                                                                                                                                                            |
|                                                                                          | postrouting        |              | 225      | NF\_IP\_PRI\_SELINUX\_LAST       | SELinux at packet exit                                                                                                                                                                                |
| inet, ip, ip6                                                                            | postrouting        |              | 300      | NF\_IP\_PRI\_CONNTRACK\_HELPER   | Connection tracking helpers, which identify expected and related packets.                                                                                                                             |
| inet, ip, ip6                                                                            | input, postrouting |              | INT\_MAX | NF\_IP\_PRI\_CONNTRACK\_CONFIRM  | Connection tracking adds new tracked connections at final step in input & postrouting hooks.                                                                                                          |
|                                                                                          |                    |              |          |                                  |                                                                                                                                                                                                       |
| bridge                                                                                   | prerouting         | **dstnat**   | -300     | NF\_BR\_PRI\_NAT\_DST\_BRIDGED   |                                                                                                                                                                                                       |
| bridge                                                                                   | all                | **filter**   | -200     | NF\_BR\_PRI\_FILTER\_BRIDGED     |                                                                                                                                                                                                       |
| bridge                                                                                   |                    |              | 0        | NF\_BR\_PRI\_BRNF                |                                                                                                                                                                                                       |
| bridge                                                                                   | output             | **out**      | 100      | NF\_BR\_PRI\_NAT\_DST\_OTHER     |                                                                                                                                                                                                       |
| bridge                                                                                   |                    |              | 200      | NF\_BR\_PRI\_FILTER\_OTHER       |                                                                                                                                                                                                       |
| bridge                                                                                   | postrouting        | **srcnat**   | 300      | NF\_BR\_PRI\_NAT\_SRC            |                                                                                                                                                                                                       |

## 参考源

1. [nftables wiki](https://wiki.nftables.org/wiki-nftables/index.php/Main_Page)
2. [nftables manpage](https://www.netfilter.org/projects/nftables/manpage.html)
3. [Quick reference-nftables in 10 minutes](https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes)


# Linux 30 周年

Linus 受访发言节选

## 开源社区

### 如何成功

> 这是一个很难回答的问题，因为**我真的不知道成功的关键是什么**。虽然 Linux 非常成功，Git 也站稳了脚跟，但我很难说二者成功的深层次原因究竟是什么。天时、地利、人和都非常重要。对于 Linux 和 Git 来说，最重要的是这两个项目恰好满足了很多人的需求，或者是因为很多人都有这样的需求，但我是唯一一个站出来创建了这样的项目，并取得了成功的人？我个人更倾向于后者，**选择很重要，运气也很重要**。
>
> 另一方面，我觉得对于开源维护者而言，确实需要一些**务实的精神和思想，这很重要**。

### 转折点

> 最大的转折点是当我意识到真有人在使用它，并对它感兴趣时，它开始有了自己的生命。

### 激励

> **金钱其实并不是一个很好的激励方式**，因为它并不能将人们团结在一起。我认为，真正能够起到激励作用的是：**人们参与到一个共同的项目中来，并真正感觉到自己可以成为这个项目的全面合作伙伴**。

### 放权

> 很多人都会觉得“放权”很难。其实早年间有人给我发送补丁，但我并没有直接使用，我会阅读他们的代码，搞清楚他们想要什么，然后自己重新写代码。然而事实证明，我这样做并没有什么用，因为我很懒，所以决定在阅读并理解补丁后直接使用。因此，我眷恋权力的日子很快就过去了。**信任他们，不要对他们进行过多的微管理。**
>
> 因此，将项目委托给别人也不是一个大问题（当然我知道有些项目情况大不同），归根结底，部分原因是**我们的维护模型不需要某种绝对的信任**，因此情况就简单了许多。
>
> 另外，**沟通技巧非常重要**。**我出生于一个新闻记者家庭，读书和写作是每个人都喜欢的事情**。虽然英语是我的第三语言，但是当我建立 Linux 项目的时候，已经可以熟练地使用英语交流了。总的来说，大部分时间里，我都是在一边工作一边学习。再说一次，Linux 的成功不是一蹴而就。我们经过了三十年的努力，这个项目才有了如今大不同的局面。

### 许可证（GPLv2）

> 我 100% 地相信许可证是 Linux（以及 Git）成功的重要组成部分。我始终坚信要让大家都知道自己具有平等的权利且没有人在许可方面享有特权，这对所有人来说都是一件好事。
>
> 我认为 GPLv2 能够实现 **“所有人都在相同规则下工作”** 与 **“要求人们回馈社区”** 的完美平衡，大家都受同样的规则约束，非常公平公正。
>
> 同样，你的投入也会得到相应的回报。你可以当项目的“旁观者”，但也就失去了项目的控制权；也可以只把 Linux 当做一个基本的操作系统；但如果你有特殊要求，那么能对项目产生真正影响的唯一方法就是参与进来。
>
> 在这种情况下，包括我在内的所有人都要保持诚实。任何人都可以对项目进行分叉，走自己的路，然后接管自己的 Linux 版本维护。我的特别仅仅在于人们相信我能把工作做好，而这本就是理所当然的事情。
>
> “任何人都可以维护自己的版本”这一点让一些人对 GPLv2 产生了怀疑，但我认为这是一种优势。正是这一点保护 Linux 逃过了分裂的结局：每个人都可以完成自己的项目分支。事实上，这也是“Git”的核心设计原则之一——存储库的每个克隆都是自己的小分支，开发者（或公司）要想真正完成项目开发的话，则需要从中分叉出去。
>
> 所以**分叉本身不是问题，只要你能把好的部分合并回来即可**，这就是 GPLv2 的意义所在。要保障大家具备进行分叉并实现个人项目的权利，但与此同时，也要保证当分叉成功时，大家也有权利能再次将其融合回来。
>
> 另一个问题是，大家都想拥有能够支持项目生产的工具，与此同时，心态也一定要强大。将分叉融合回来的障碍，不仅是许可证，还有“Bad Blood”的问题。如果两个分叉从根本上就非常对立的话，那么要想将它们融合是非常困难的——并不是因为许可证或技术原因，而是由于分叉过于尖锐对立。同样，我认为 Linux 很好地避免了这一点，主要是因为我们一直认为分叉是一件非常正常且自然的事情；当其证明了自身的成功后，自然也要合并回来。
>
> 虽然这个答案或许有些跑题，但我认为这一点非常重要——我从未后悔过自己的许可证选择，因为**我真心认为 GPLv2 是 Linux 能够取得成功的重要原因**。

## 内核开发

### 引以为傲

> 个人认为是 **VFS（虚拟文件系统）层，尤其是路径名查找和我们的 VM 代码**。前者是因为 Linux 在做基础任务时表现确实非常优秀（在操作系统中查找文件名就是操作系统中的基础核心操作）。后者主要是因为我们支持 20 多种架构，但仍使用基本统一的 VM 层，我认为这一点非常了不起。但与此同时，这很大程度上取决于“更注重内核的哪一部分”。**我个人在 VM 和 VFS 领域的参与更多，因此自然也会选择这两方面的内容。**

### 版本发布

> 几十年来，我们推出过许多不同的版本方案以及多个开发模式，但 3.0 版本最终确定了我们一直以来使用的模式。它真正实现了 **“基于时间，版本号只是数字，不依附于任何功能”** 的说法。在 2.6 版本中，就具备合并窗口的“基于时间”的概念，因此这并不稀奇，但 3.0 是“最后一片拼图”。
>
> 我们有随机编号方案（主要是在 1.0 之前），其规则是：**小数点后奇数表示开发内核，偶数表示稳定的生产内核**。在 2.6 中，我们开始做基于时间的发布模式。但仍然存在“何时增加主版本号”的问题。而 3.0 的正式出现表示，**主版本号并没有什么特殊意义**，只是为了尽量简化数字，不要让它太长太繁琐。

### 内核重构

> \*\*我们真的非常擅长完全重写，所以如果有不尽如人意的地方也早就被重写了。\*\*我们也有很多“兼容”层，但一般无伤大雅。而且尚不清楚如果重写的话，那些兼容层是否会真的消失——它们是对旧二进制文件的向后兼容（通常是对旧体系结构的向后兼容性，例如在 x86-64 上运行 32 位 x86 应用程序）。我认为向后兼容是非常重要的，所以希望即使在重写时也要保持这种兼容性。
>
> 显然，很多东西都不是“最优选”，都有改进的空间，确实有一些没人关心和清理的遗留驱动，并可能会被利用来做一些坏事，但重点是“没人关心”。所以当问题出现时，我们想要去积极主动解决根源问题——“没人关心”。因此多年来，**当架构维护不再具有意义时，我们就会直接放弃整个架构支持**。
>
> 不过，**重写的唯一主要原因是——整个架构已经没意义了**，但却还有一些用例。最有可能的情况是，一些小型嵌入式系统并不需要 Linux 提供的东西，而且其硬件空间很小，它需要的是比 Linux 更小、更简单的东西。因为 Linux 已经成长了很多。现在，即使是小硬件（比如手机等）也比当初开发 Linux 时使用的机器功能强大得多。

### Rust

> 还需要再观察。\*\*我不认为 Rust 会接管内核，但是做单独的驱动程序（或整个驱动子系统）还是有可能的，或许还能做文件系统。\*\*所以它 **不是要“取代 C 语言”，而是“在适当的地方增强 C”** 。
>
> 特别是驱动程序约占实际内核代码的一半，所以空间非常大，但我不认为有人真的会用 Rust 全盘重写现有的驱动程序。绝大多数人都会“用 Rust 做新的驱动程序，在适当的地方重写几个驱动程序”。
>
> 但现在更多的人仍处于“试着玩玩”的阶段。**要指出优点很容易，但其背后存在着复杂性，所以我更愿意持观望态度，看看其承诺的优点是否真的能实现。**

## Git

### 诞生

> **我并不想创建新的源码控制系统，Git 的诞生完全是出于需要。并不是我觉得源代码控制很有意思，而是因为我完全看不上当时市面上大多数源代码控制系统，包括在 Linux 开发模型中运行得很好的 BitKeeper 也无法满足我的需求了。**

### **移交**

> 相比之下，我做 Linux 已经有三十多年（加上研究的时间)，并且一直在对其进行维护，但我从未想过要长期维护 Git。**我喜欢使用 Git，而且我认为它是目前市面上最好的 SCM，但这不是我的热情和兴趣所在**，因此，我一直希望由别人来替我维护 SCM。
>
> 至于 Junio，他是最早加入 Git 开发队伍的人之一。他在我公开了第一版 Git（非常粗糙的一版）后的几天内便完成了首次改动。所以 **Junio 实际上从 Git 诞生之初就已经是我们中的一员了**。
>
> 但之所以把项目交给 Junio，并不只是因为他“来得早”。在维护了 Git 几个月后，真正让我决定邀请 Junio 担任维护者的因素，是一个比较抽象的概念——**“好品味”**。编程依赖的也是各种细枝末节和每日的繁重工作，偶尔也会需要所谓的“灵感”，即“好品味”，**它能干净、漂亮，甚至是完美地解决问题**。编程是为了解决技术问题，但如何解决这些问题，以及如何思考也是非常重要的。随着时间的推移，你会清楚地认识到：有些人就是有那种“好品味”，能够做出“正确的”选择。
>
> 而 Junio 就具备这种“好品味”。
>
> 每次提到 Git，我都会尽量讲得非常清楚，虽然确实是我提出并设计了 Git 的核心思想，但 **Git 这十五年来，我只有在第一年亲自参与了项目工作，Junio 一直都是一名优秀的维护者，是他让 Git 有了今天的成就**。
>
> 找到并信任具备“好品味”的人——这不仅仅是 Git 的故事，也是 Linux 的历史。与 Git 不同的是，Linux 是一个我仍积极亲自参与维护的项目；但与 Gi t 相同的是，它也是一个有很多人参与的项目。**我认为 Linux 的一大成功之处就在于有数百名的维护者，他们都具备难以言表的“好品味” ，齐心协力共同维护内核。**


# 新时代 Linux 命令

技术迭代，命令更替

### [bat](https://github.com/sharkdp/bat)

![bat](/files/-MeGyiVqotozD1Kq-Zn0)

#### 功能

在 `cat` 基础上增加了 **语法高亮**。

#### 安装命令

```bash
pacman -S bat
```

### [progress](https://github.com/Xfennec/progress)

![progress](/files/-MeGXfk-5uOjBYqwd_h9)

#### 功能

查找当前在您的系统上运行的 coreutils 基本命令（cp、mv、dd、tar、gzip/gunzip、cat 等）并显示复制数据的 **百分比、估计的时间 和 吞吐量**。

#### 安装命令

```bash
pacman -S progress 
```

### [icdiff](https://github.com/Xfennec/progress)

![icdiff](/files/-MeGXZS_0APDGiDBl85K)

#### 功能

在传统 `diff` 的基础上扩展了 **左右** **色彩** 对比。

#### 安装命令

```bash
pip install git+https://github.com/jeffkaufman/icdiff.git
```

### [ag](https://github.com/ggreer/the_silver_searcher)

![ag](/files/-MeGbC8LAwKimJZDiuVN)

#### 功能

闪电搜索，`ack` 的直接后代，也可以替代 `grep` 。

#### 安装命令

```bash
pacman -S the_silver_searcher
```

### [glances](https://github.com/nicolargo/glances)

![glances](/files/-MeGbYUkQQ9tbxjABeXA)

![glances](/files/-MeGb_jUyrCbn_6mMEvn)

**功能**

替代 `htop`，**跨平台**的系统状态监控（支持 **Web**）。

#### 安装命令

```bash
pacman -S glances
```

### [tig](https://jonas.github.io/tig/)

![](/files/-MeS_wE1RGW6CZlVfmgk)

![tig](/files/-MeGk4PXtqSkCMP_m_Z_)

####

#### 功能

基于 `ncures` 的 **git 浏览器**。

#### 安装命令

```bash
pacman -S tig
```

### [fzf](https://github.com/junegunn/fzf)

![fzf](/files/-MeGnghlkULxy43KM52M)

#### 功能

通用的命令行 **模糊查找** 器。

#### 安装命令

```bash
pacman -S fzf
```

### [cloc](https://github.com/AlDanial/cloc)

![cloc](/files/-MeGrOay72NM_-VDwXFQ)

#### 功能

计算 **代码行数** 。

#### 安装命令

```bash
pacman -S cloc
```

### [ncdu](https://dev.yorhel.nl/ncdu)

![ncdu](/files/-MeGqvsc7RBqLeZ13dES)

#### 功能

基于 `ncurses`磁盘使用分析器，替代 `du` 。

#### 安装命令

```bash
pacman -S ncdu
```


# Arch Linux UKI 启动

systemd-boot、UKI 与 DPS

## 前提

本文假设：

1. 系统使用 UEFI、GPT、`systemd-boot`、`mkinitcpio`。
2. 根文件系统是 Btrfs，系统子卷类似 `@`。
3. ESP 和 root 在同一块物理磁盘上。
4. `mkinitcpio` 使用 `systemd` initramfs hook。没有这个 hook，root 分区不能只靠 DPS 自动发现。
5. root 没有跨盘、RAID 或加密层。
6. CPU 微代码包按机器实际情况选择：AMD 使用 `amd-ucode`，Intel 使用 `intel-ucode`。

操作前先确认分区与挂载关系：

```bash
findmnt / /boot /efi
lsblk -f
sudo sgdisk -p /dev/nvme0n1
```

下面命令里的磁盘、分区号、UUID 都要替换成自己的实际值。

## 启用 systemd initramfs

省略 `root=` 依赖 initrd 阶段的 `systemd-gpt-auto-generator`。清空内核命令行之前，先确认 `/etc/mkinitcpio.conf` 里的 `HOOKS` 已经从传统 busybox 流程切到 `systemd` 流程：

```bash
grep '^HOOKS=' /etc/mkinitcpio.conf
```

普通未加密 Btrfs root 至少要包含 `systemd`、`block`、`filesystems`。如果原配置还在使用 `udev`，要先按自己的磁盘、键盘和文件系统情况迁移到 systemd hook 体系。加密 root、LVM、RAID 等场景需要对应的 systemd initramfs hook，不在本文范围内。

## 迁移 ESP 挂载点

把 ESP 从 `/boot` 迁移到 `/efi`，修改 `/etc/fstab` 中 ESP 对应行：

```
UUID=XXXX-XXXX  /efi  vfat  noauto,x-systemd.automount,x-systemd.idle-timeout=60s,umask=0077,errors=remount-ro  0 2
```

重新挂载，并重装内核与微代码。这样原本写进 ESP 的内核文件会释放到 Btrfs 管理的 `/boot` 目录下：

```bash
sudo umount /boot
sudo mkdir -p /efi
sudo mount /efi
sudo pacman -S linux amd-ucode
```

Intel CPU 把最后一行替换成：

```bash
sudo pacman -S linux intel-ucode
```

## 设置 Btrfs 默认子卷

先找出系统根子卷 ID，例如 `@` 对应的 ID：

```bash
sudo btrfs subvolume list /
```

假设目标 ID 是 `256`，把它设成文件系统默认挂载子卷：

```bash
sudo btrfs subvolume set-default 256 /
```

这一步的意义是把“默认挂哪个子卷”写进 Btrfs 文件系统本身，而不是继续依赖内核命令行里的 `rootflags=subvol=`。

## 设置 DPS 分区类型

DPS 依赖 GPT 分区类型。以 `/dev/nvme0n1` 为例，假设 ESP 是第 1 个分区，root 是第 3 个分区：

```bash
sudo sgdisk -t 1:ef00 /dev/nvme0n1
sudo sgdisk -t 3:8304 /dev/nvme0n1
```

其中：

1. `ef00` 是 EFI System。
2. `8304` 是 Linux x86-64 root。

ARM64、RISC-V 等架构要换成对应的 root 分区类型。修改后可以检查一次：

```bash
sudo sgdisk -p /dev/nvme0n1
```

## 清空内核命令行

保留一个空的 `/etc/kernel/cmdline`，避免生成 UKI 时回退读取 `/proc/cmdline` 里的旧参数：

```bash
sudo sh -c '> /etc/kernel/cmdline'
```

如果仍然需要 `quiet`、`loglevel=`、`lsm=` 等参数，再显式写入这个文件。要做纯自动发现启动，就保持为空。

## 修改 mkinitcpio 预设

编辑 `/etc/mkinitcpio.d/linux.preset`，关闭传统 initramfs `img` 输出，启用 UKI 输出：

```ini
ALL_kver="/boot/vmlinuz-linux"
PRESETS=('default' 'fallback')

default_uki="/efi/EFI/Linux/arch-linux.efi"
fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"
```

重点是删除或注释掉这些传统输出项：

```ini
default_image="/boot/initramfs-linux.img"
fallback_image="/boot/initramfs-linux-fallback.img"
```

## 重建引导环境

确认 `/efi` 已经挂载到 ESP 后，再删除本文会重新生成的旧启动产物：

```bash
findmnt /efi
sudo rm -rf /efi/EFI/Linux
sudo rm -rf /efi/loader
sudo bootctl install
sudo mkdir -p /efi/EFI/Linux
sudo mkinitcpio -P
```

删除 `/efi/EFI/Linux` 和 `/efi/loader` 只应该在确认 `/efi` 正确挂载 ESP 后执行。否则删的就是根文件系统里的普通目录。

## 验证

检查 `systemd-boot` 是否识别到 UKI：

```bash
bootctl list
```

看到 `arch-linux.efi` 对应条目显示为 `Type #2 (UKI, .efi)` 后，即可重启验证。

## 参考

1. [ArchWiki: Unified kernel image](https://wiki.archlinux.org/title/Unified_kernel_image)
2. [sd-boot(7)](https://www.freedesktop.org/software/systemd/man/latest/sd-boot.html)
3. [systemd-gpt-auto-generator(8)](https://www.freedesktop.org/software/systemd/man/devel/systemd-gpt-auto-generator.html)
4. [Discoverable Partitions Specification](https://uapi-group.org/specifications/specs/discoverable_partitions_specification/)


# 树莓派实时性优化

天下武功，唯快不破

## 优化目的

项目需要用 **树莓派 4B** 实现 **毫秒级控制**，并且误差控制在 **5%** 内（即 **0.05ms = 50us**）。\
本身这种精度的控制应该考虑由 C 实现，但考虑到以下原因，最终还是选用了 **Python** 作为主语言。

1. 用惯了 Python，好久好久没有写过 C 了，真的 **不想写 C** 啊啊啊啊 (/▽＼)
2. 控制过程中 Python 调用的 **包多是封装了底层 C 库实现，实际性能并不差**
3. 整体程序框架中，**需要 Python 实现的顶层控制非常简单**

那么，**为了实现 50 us 的控制精度，咱就需要针对树莓派上运行的 Raspberry Pi OS 及 Python 进程 进行优化**。

## 优化内容

优化的主要思路参考了下面的两篇文章：

* [树莓派提高实时性的几种方式 (使用 python 测试)](https://jianshu.com/p/47d5d89c164c)
* [四足机器人高算力、低成本主控第一步：给树莓派打上 RT 实时补丁](https://zhuanlan.zhihu.com/p/358151393)

### 提升 Python 进程优先级

#### 操作

**1. 首先需要安装 `wiringpi` 包：**

```bash
sudo pip3 install wiringpi
```

**2. 其次需要在程序中加入以下内容：**

```python
import wiringpi
wiringpi.piHiPri(99)
```

#### 原理

`wiringpi` 中的 `piHiPri` 函数通过调用 Linux 内核的 API，改变了当前进程的调度策略及优先级进一步提高了实时性。这和 Python 中标准库的 `os.setpriority` 不同，`os.setpriority` 并未改变调度策略，实际优化效果很有限。需要注意的是，此处设置的优先级是用于比较的相对值，严格地说并不是越大就越好。

{% hint style="info" %}

> The priority parameter works relative to others – so you can make one program priority 1 and another priority 2 and it will have the same effect as setting one to 10 and the other to 90 (as long as no other programs are running with elevated priorities)

priority 参数 **相对** 于其他参数有效 - 因此您可以将一个程序的优先级设置为 1，将另一个程序的优先级设置为 2，其效果与将一个设置为 10，另一个设置为 90 相同（只要没有其他程序以更高的优先级运行）。
{% endhint %}

### 绑定独立 CPU

#### 操作

**1. 首先需要更改内核启动参数：**

```bash
sudo sed -i.bak -e 's/$/ isolcpus=3/' /boot/cmdline.txt
```

{% hint style="warning" %}
**！！！请注意：单引号中的空格为必须！！！**\
\&#xNAN;***其中 `3` 可以更改为你想要指定的 CPU 编号（树莓派 4B 中 CPU 编号为 0-3)。***\
\&#xNAN;*考虑到未来可能需要还原，此步将原文件添加 .bak 后缀进行了备份。*
{% endhint %}

**2. 接着安装后面要用到的 `psutil` 包**

```bash
sudo pip3 install psutil
```

**3. 最后在程序中加入以下内容：**

```python
import psutil
current_process = psutil.Process()
current_process.cpu_affinity([3])
```

{% hint style="info" %}
*此处的 `3` 为上文提到的 CPU 编号*
{% endhint %}

#### 原理

首先让系统不会主动调度程序到指定 CPU 上运行，也就是 **保证指定 CPU 默认是完全空闲** 的状态。其次让 **程序主动要求在指定 CPU 上运行**。这样程序就完成了 **对指定 CPU 的独享**。

### 打内核 RT 补丁

#### 操作

**1. 这里作者选择直接下载编译好的内核：**

### [**rt-kernel.tgz**](https://github.com/lemariva/RT-Tools-RPi/blob/4fb1bb511d1701d5b0975314ac1ec87b792f9530/preempt-rt/kernel_4_19_59-rt23-v7l+/rt-kernel.tgz) <a href="#blob-path" id="blob-path"></a>

链接源自 Github，所以需要科学上网，你懂的 (￣\_￣ )

{% hint style="info" %}
如果你想要亲手编译内核，可参考以下资料：

1. [Raspberry Pi: Real Time System - Preempt-RT Patching Tutorial for Kernel 4.14.y](https://lemariva.com/blog/2018/07/raspberry-pi-preempt-rt-patching-tutorial-for-kernel-4-14-y)
2. [四足机器人高算力、低成本主控第一步：给树莓派打上 RT 实时补丁](https://zhuanlan.zhihu.com/p/358151393)
3. [Raspberry Pi OS Linux Kernel building](https://www.raspberrypi.org/documentation/linux/kernel/building.md)
4. [preemptrt\_setup](https://wiki.linuxfoundation.org/realtime/documentation/howto/applications/preemptrt_setup)

*由于涉及内容相对庞杂，且作者在此方面经验尚浅，故不做展开。*
{% endhint %}

**2. 将下载的压缩包传至树莓派 /tmp 目录下：**

*基础操作，如不理解请善用搜索引擎*

**3. 依次运行以下命令：**

```bash
sudo -i
cd /tmp
mkdir rt-kernel
tar -xzvf rt-kernel.tgz -C rt-kernel
cp -Rdf rt-kernel/boot/* /boot/
cp -Rdf rt-kernel/lib/* /lib/
cp -Rdf rt-kernel/overlays/* /boot/overlays/
cp -Rdf rt-kernel/bcm* /boot/
echo 'kernel=kernel7_rt.img' >> /boot/config.txt
```

**4. 重启系统：**

```bash
sync
reboot
```

**5. 检查内核版本：**

```bash
uanme -r
```

若输出为 `4.19.59-rt23-v7l+`，说明安装成功。

#### 原理

> Linux 是典型的 **分时应用系统** ，对于实时性要求很高的应用，必须对内核本身动手术。而 RTLinux 则采取了一种比较聪明也比较折中的办法：他们实现一个最底层的精简的调度器，用于调度实时线程，原来的内核本身则成为实时调度器的一个优先级最低的任务。这样，当有实时任务时，普通内核已经建立于其上的普通进程被强制中断，实时线程被强制执行；只有当若有实时线程都让出 cpu 之后，普通内核才被运行，再由普通内核去调度执行普通的应用程序。

## 性能测试

### 测试方法

1. 用 `rt-tests` 软件包中的 `cyclictest` 工具测试系统实时性：

   ```bash
   # 安装 rt-tests 软件包
   sudo apt install rt-tests
   # 实际运行测试的命令，--duration 指定测试时长，此处为 1 分钟
   cyclictest --mlockall --smp --priority=80 --interval=100 --distance=0 --duration=1m
   ```
2. 用以下程序测试程序实时性：

   ```python
   from time import monotonic, sleep
   from array import array
   from statistics import mean

   i = 0
   data = array("f")
   while i < 60000:
       t0 = monotonic()
       sleep(0.001)
       t1 = monotonic()
       data.append((t1 - t0 - 0.001) * 1000000)
       i += 1
   print("AVG: %.2f us" % mean(data))
   print("MAX: %.2f us" % max(data))
   print("MIN: %.2f us" % min(data))
   ```

### 测试数据

#### 优化前

```bash
policy: fifo: loadavg: 0.55 0.66 0.36 1/293 2309

T: 0 ( 2303) P:80 I:100 C: 599954 Min:      6 Act:   18 Avg:   15 Max:     936
T: 1 ( 2304) P:80 I:100 C: 599498 Min:      5 Act:   18 Avg:   15 Max:     382
T: 2 ( 2305) P:80 I:100 C: 599062 Min:      5 Act:   18 Avg:   14 Max:    1482
T: 3 ( 2306) P:80 I:100 C: 598541 Min:      6 Act:   19 Avg:   14 Max:    5696
```

{% hint style="success" %}
**AVG: 82.94 us**\
**MAX: 6550.83 us**\
**MIN: 32.67 us**
{% endhint %}

#### 优化后

```bash
policy: fifo: loadavg: 2.38 1.39 0.64 1/308 1491


T: 0 ( 1471) P:80 I:100 C: 599898 Min:      5 Act:   20 Avg:   13 Max:      95
T: 1 ( 1472) P:80 I:100 C: 599418 Min:      6 Act:   18 Avg:   13 Max:     114
T: 2 ( 1473) P:80 I:100 C: 598916 Min:      5 Act:   18 Avg:   13 Max:     102
T: 3 ( 1474) P:80 I:100 C: 598534 Min:      6 Act:   21 Avg:   14 Max:      34
```

{% hint style="info" %}
**AVG: 82.94 us**\
**MAX: 6550.83 us**\
**MIN: 32.67 us**
{% endhint %}

#### 网上已有的树莓派 3B+ 上的具体性能测试数据

{% hint style="warning" %}
请注意，此处并非本次优化的数据。
{% endhint %}

![](/files/-Mf7-fgGt5VPhD84xw05)

![](/files/-Mf7-q0qD-pe0OknFQZy)

### 测试结论

从以上数据可以看出，系统实时性提升主要体现在 **极值** 的降低上。

**在实际程序中，均值与极值都有非常可观的降低。**\
\&#xNAN;*优化完成后，手头 Python 运行的测试误差为 30 us 左右，考虑到项目可容许的偏差是 50 us，终于——咱不用去写 C 啦！o(￣▽￣) ブ*

## 参考源

1. [树莓派提高实时性的几种方式 (使用 python 测试)](https://jianshu.com/p/47d5d89c164c)
2. [四足机器人高算力、低成本主控第一步：给树莓派打上 RT 实时补丁](https://zhuanlan.zhihu.com/p/358151393)
3. [Wiring Pi -- GPIO Interface library for the Raspberry Pi](http://wiringpi.com/reference/priority-interrupts-and-threads)
4. [preemptrt\_setup](https://wiki.linuxfoundation.org/realtime/documentation/howto/applications/preemptrt_setup)
5. [sched\_setscheduler() 函数](https://blog.csdn.net/wennuanddianbo/article/details/79304869)
6. [Raspberry Pi OS Linux Kernel building](https://www.raspberrypi.org/documentation/linux/kernel/building.md)
7. [psutil.Process.cpu\_affinity](https://psutil.readthedocs.io/en/latest/#psutil.Process.cpu_affinity)
8. [Cyclictest Wiki](https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/cyclictest/start)
9. [wiringPi/piHiPri.c](https://github.com/WiringPi/WiringPi/blob/5c6bab7d4279e8c0cc890984eaa1a69ff3af1c99/wiringPi/piHiPri.c)
10. [sched.7](https://man7.org/linux/man-pages/man7/sched.7.html)
11. [Raspberry Pi: Real Time System - Preempt-RT Patching Tutorial for Kernel 4.14.y](https://lemariva.com/blog/2018/07/raspberry-pi-preempt-rt-patching-tutorial-for-kernel-4-14-y)
12. [Rapberry Pi: Preempt-RT Kernel Performance on Rasbperry PI 3 Model B+](https://lemariva.com/blog/2018/04/rapberry-pi-preempt-rt-kernel-performance-on-rasbperry-pi-3-model-b)


# Bash DEBUG 一行搞定

脚本写着爽，DEBUG 火葬场

```bash
set -Eeuxo pipefail
```

* `-E` 让 `trap` 能够捕获函数内信号。
* `-e` 非零返回值终止执行。
* `-u` 读取不存在的变量会报错并停止执行。
* `-x` 执行前打印指令内容。
* `-o pipefail` 子命令失败将使管道返回非零并终止执行。


# 如何在大型集群中加速 Pod 的启动？

KubeCon + CloudNativeCon + Open Source Summit China 2023 技术分享

本文整理自 Paco Xu（DaoCloud）与 Byron Wang（Birentech）在 KubeCon + CloudNativeCon + Open Source Summit China 2023 的技术分享。

## 一、背景与 Pod 启动耗时的定义

常言道：“良好的开端是成功的一半”（A work well begun is half-ended）。 对 Pod 而言同样如此：Pod 在生命周期中所面临的绝大多数初始化、网络、挂载及配置问题，都集中在启动这一短暂的窗口期。 一旦 Pod 跨过启动阶段并稳定运行，后续出现组件配合问题的概率将大幅降低。 因此，深入研究并优化 Pod 的启动过程，对于维护大规模集群的稳定性具有极高的价值。

在讨论如何加速启动之前，首先需要明确一个基准：**Pod 启动多快才算快？一个正常 Pod 的启动耗时应该在什么范围内？**

根据常见的应用场景，Pod 启动耗时大致可划分为以下几个梯队：

* **轻量级 Pod**（`< 50ms`）：通常为极简的无状态微服务，无外部卷依赖，且运行节点上已缓存镜像。
* **高度优化的 Pod**（`~ 100ms`）：镜像经过精简，容器运行时（Runtime）及网络插件（CNI）经过高度调优。
* **常规 Pod**（`数秒级`）：绝大多数业务应用的正常启动范围。
* **重型 Pod**（`15s ~ 1min`）：镜像体积较大（如 AI 训练镜像、重型 Java 应用），或涉及复杂的网络配置与远程存储卷挂载。
* **极端延迟 Pod**（`> 5min`）：通常由大镜像拉取超时、网络拥堵、存储挂载失败或初始化容器（Init Container）阻塞引起。

优化的核心目标，就是将重型 Pod 的启动时间尽量压缩至秒级，同时确保常规 Pod 稳定保持在毫秒级到亚秒级的水平。

## 二、Pod 创建阶段的加速（API Server）

Pod 的创建通常由 Controller（如 Deployment Controller）或自定义 Operator 发起。 API Server 及底层存储 etcd 的响应速度，直接决定了 Pod 创建的第一步效率。

### 1. API Server 响应变慢的根本原因

* **etcd 性能瓶颈**：etcd 读写延迟高、磁盘 I/O 压力大或 etcd 负载过高。
* **API Server 高负载**：API Server 本身 CPU/内存资源不足，导致请求排队。
* **并发限流（Rate Limit）**：请求频率触发了 API Server 的流控阈值。
* **Webhook 延迟过高**：集群中注册的 Mutating Webhook 或 Validating Webhook 响应缓慢，这是最常见的影响创建速度的“元凶”。

### 2. Pod 创建失败或处于 Pending 状态的常见诱因

* **校验失败（Validation Failure）**：配置格式或权限不合规。
* **安全策略拦截**：如 Pod Security Admissions（PSA）检查未通过。
* **集群资源耗尽**：Pod 处于排队等待状态（如大规模批处理作业中）。 此时需合理配置 **Priority & Preemption**（优先级与抢占机制），确保关键业务 Pod 能够优先创建。
* **资源配额超限**：Namespace 级别的 ResourceQuota 已达上限。

**优化策略**：对 API Server 和 etcd 进行性能调优（如升级 SSD、调大并发处理线程），严格控制并优化自定义 Webhook 的代码逻辑与响应时间，并在大规模并发创建时合理使用优先级抢占机制。

## 三、Pod 调度阶段的加速（Scheduler）

若 Pod Spec 中未明确指定 `nodeName`，则必须通过 `kube-scheduler` 寻找合适的节点。 在大规模集群中，调度延迟会随着节点数量和调度规则复杂度上升。

### 1. 调度阶段的瓶颈分析

* **调度失败与重试**：调度器内部拥有重试队列（Retry Queue）。 当调度变慢时，不一定是调度器性能问题，往往是由于调度条件不满足导致 Pod 被频繁退回到重试队列，从而消耗了调度器的计算资源。
* **集群规模过大**：节点基数庞大导致调度器在进行评分（Scoring）和过滤（Filtering）时计算量激增。 可通过调低 `percentageOfNodesToScore` 参数，限制参与评分的节点比例。
* **拓扑与亲和性规则过于复杂**：大量使用深度的 Node Affinity、Pod Affinity 或 Pod Anti-Affinity 规则，会显著增加调度器的算法复杂度。

### 2. 调度侧加速方案

* **负载感知调度（Load-Aware Scheduling）**：原生的调度算法主要基于资源的 Request 进行静态计算。 通过引入社区的 Trimaran 插件，调度器可以感知集群节点的真实运行负载（Real Load），优先将 Pod 调度到实际负载较低的节点上，避免 Pod 在启动瞬间因物理节点 CPU 争抢而卡顿。
* **打散策略（Spread Strategy）**：尽量避免将大批量同时启动的 Pod 调度到同一个物理节点上。 通过在不同可用区（Zone）或 Node 间进行打散调度，可以有效分摊镜像拉取、网络 I/O 及 CPU 消耗压力，防止单节点瞬时过载拖慢整体启动进度。

## 四、GPU / AI 场景下的资源调度与分配机制

在 AI 和大模型训练场景下，Pod 往往需要独占或共享 GPU 资源。 异构资源的调度和分配机制与常规 CPU/内存有着本质的区别。

```
                    +--------------------+
                    |    API Server      |
                    +---------+----------+
                              |
                     (Request GPU Resource)
                              |
                              v
                    +---------+----------+
                    |   Kube-Scheduler   |
                    +---------+----------+
                              |
               (Bind Pod to Node via GPUBinding)
                              |
                              v
+-----------------------------+-----------------------------+
| Kubernetes Node                                           |
|                                                           |
|    +------------------+             +------------------+  |
|    |     Kubelet      |             |    Node Agent    |  |
|    +--------+---------+             +--------+---------+  |
|             |                                |            |
|     (Allocate Request)               (Read GPUBinding)    |
|             |                                |            |
|             v                                v            |
|    +--------+---------+             +--------+---------+  |
|    |  Device Plugin   +<------------+   Symlink File   |  |
|    |  (Fake Device)   |             | (Actual Physical |  |
|    +------------------+             |     GPU Card)    |  |
|                                     +------------------+  |
+-----------------------------------------------------------+
```

### 1. 传统的 Device Plugin 机制

Kubernetes 原生通过 Device Plugin 扩展异构资源的支持。 设备插件向 Kubelet 注册 Unix Socket，上报本地可用设备（如 GPU、RDMA），Pod 通过 `resources.limits` 进行显式申请。

**原生 Device Plugin 机制的局限性**：

1. **无法感知动态属性变化**：例如 FPGA 的动态重编程或设备硬件发生热插拔。
2. **型号区分模糊**：同一厂商（如 NVIDIA）的不同硬件型号（如 RTX 3090、A100）在原生机制下会被统一识别为 `nvidia.com/gpu`，调度器无法做到型号级精细化匹配。
3. **异构混部复杂**：同一集群内如果同时存在 NVIDIA、AMD 及国产算力芯片，需要部署和维护多套不同的 Device Plugin。
4. **不支持多物理卡精细化分配与拓扑感知**：Kubelet 在收到调度结果后，会在本地“随机”挑选卡，调度器无法在全局层面上干预“具体分配 0 号卡还是 7 号卡”，从而无法优化 NVLink 或 PCIe 的拓扑通信结构。

### 2. GPU 场景下的核心调度算法

为支撑 AI 并行计算，调度器层面需要实现以下高级算法：

* **Gang Scheduling（组调度 / All-or-Nothing）**：大模型分布式训练需要多个 Worker 协同。 调度器必须保证同一个 Job 下的所有 Pod 要么全部调度成功，要么一个都不调度，避免部分 Pod 抢占了资源却因人数不足而无限挂起，造成整批 GPU 资源死锁。
* **SKU / 等比例分配**：物理节点的 CPU、内存、GPU 与 RDMA 通常存在最佳绑定配比。 调度时需进行多维度等比例计算，防止 CPU 被非 AI 任务单方面占满而导致 GPU 空置。
* **Binpack（装箱算法）与 DRF（主导资源公平算法）**：Binpack 负责尽量堆满单个节点以留出完整的空闲节点；DRF 则在多租户场景下，保证各队列能够公平、不饿死地获取其主导资源。

## 五、节点侧的 Pod 启动加速（Node / Kubelet）

当 Pod 绑定到节点后，Kubelet 接管其生命周期。 此阶段是 Pod 启动耗时的重灾区，主要包含四大步骤：**拉取镜像 -> 创建 Sandbox（CNI）-> 挂载卷（Volume）-> 启动主进程**。

### 1. 定位启动瓶颈的“控制变量法”

当节点上的 Pod 启动缓慢时，可通过以下手段进行快速排查定位：

1. **提前手动拉取镜像**：若启动速度大幅提升，说明瓶颈在于**网络带宽或镜像拉取**。
2. **配置 `hostNetwork: true` 启动**：若启动速度大幅提升，说明瓶颈在于 **CNI 网络插件分配 IP 或 Sandbox 创建**。
3. **移除所有 Volume 挂载**：若启动速度大幅提升，说明瓶颈在于**存储挂载或配置卷预热**。
4. **去除 CPU/Memory Limit 限制**：若启动速度大幅提升，说明容器在初始化时遇到了严重的 **CPU Throttling（CPU 限制流控）**。

### 2. 镜像相关优化手段

* **精简镜像体积**：
  * 在构建时合理设置 `.dockerignore` 排除非必要文件。
  * 选用极简基础镜像（如 Alpine 或 scratch）。
  * 采用多阶段构建（Multi-stage builds），剔除编译依赖。
  * 精简并压缩镜像层数（Squash Layers）。
  * **严禁在生产镜像中打包 Debug 工具**：由于 `kubectl debug` 临时容器（Ephemeral Containers）技术已非常成熟，生产镜像应保持绝对纯净。 推荐使用 wagoodman 的开源工具 `dive` 逐层分析镜像体积与效率。
* **大镜像加速分发技术**：
  * **P2P 分发**：面对动辄数十 GB 的大模型镜像，部署 Dragonfly 或 Kraken 等 P2P 镜像分发系统，可以极大缓解镜像仓库的单点带宽压力。
  * **按需加载（Lazy Pulling）**：结合 Nydus 或 stargz-snapshotter 等按需加载技术，容器无需等待整个镜像下载并解压完成即可瞬时启动，在运行过程中按需从网络拉取数据块。
* **Kubelet 并行拉取优化**：Kubelet 默认采用串行镜像拉取策略（`serializeImagePulls: true`）以保护磁盘 I/O。 在高性能 SSD 节点上，建议将 `serializeImagePulls` 设为 `false`，并合理配置 `maxParallelImagePulls` 提升拉取并发度。 目前 Kubelet 对于单个 Pod 内的多个容器镜像拉取仍为串行，社区后续将持续优化该细节。

### 3. 初始化容器（Init Containers）优化

* 仅在 Init Container 中编写绝对必要的配置动作。
* 如果存在多个 Init Container，评估是否能将其合并或进行并发处理。
* 如果可能，优先使用主容器的 `postStart` 钩子或前置 DaemonSet 预先完成节点环境准备，避免阻塞 Pod 主生命周期的演进。

### 4. CPU Limits 优化（避免启动态 CPU Throttling）

* **背景**：Java 等重型应用在启动阶段会进行大量的类加载和 JIT 编译，瞬时 CPU 需求极高（如需 2 核），但启动后日常运行仅需 0.5 核。 若在 Limit 中限制为 0.5 核，会导致启动过程极其缓慢，甚至触发健康检查超时而无限重启。
* **解决方案**：自 Kubernetes v1.27 起，原地动态调整机制（In-Place Pod Vertical Scaling）正式引入。 可以结合 VPA（Vertical Pod Autoscaler），在 Pod 启动时为其分配充足的 CPU 额度，待其 Ready 并进入稳定运行态后，再无感知地调低其 Limit，在不造成资源浪费的前提下实现启动加速。

### 5. 静态 CPU 策略绑核（Static CPU Policy）

* 在高负载或低延迟场景下，通过 Kubelet 的 Static CPU Manager 实现物理核绑定（Core Pinning），避免容器进程在物理核之间频繁切换带来的上下文开销，提升启动稳定性。
* 启用条件：Pod 的 QoS Class 必须为 `Guaranteed`（即 CPU 的 Request 等于 Limit）。
* **配置变更注意点**：将 CPU Manager 策略从 `none` 变更为 `static` 时，需要先 Drain 节点、停止 Kubelet、手动清理 CPU 状态文件（默认位于 `/var/lib/kubelet/cpu_manager_state`）、修改配置后重新拉起 Kubelet。

### 6. 健康检查探针（Probes）优化

* 合理设置 StartupProbe、ReadinessProbe 和 LivenessProbe 的阈值。 优先通过 StartupProbe 接管长周期的初始化，防止在应用启动成功前被 LivenessProbe 误杀。
* 社区目前正在推进高精度（亚秒级 / 毫秒级）探针的落地应用，未来可实现更灵敏的 Ready 状态感知。

### 7. 容器快照技术（Forensic Container Checkpointing）

自 v1.25 起，Kubernetes 引入了运行时容器快照功能。 对于启动初始化动作（如加载海量配置、JVM 内存预热）极其漫长的应用，可以在其完全 Ready 后通过快照技术（基于 CRIU 机制）导出当前的运行状态。 后续扩容或重启时，直接通过快照进行内存还原，跳过全部启动初始化，实现秒级冷启动。

### 8. SELinux 与 API QPS 调优

* **SELinux Relabeling 优化**：如果挂载的持久卷中包含海量小文件，SELinux 会在启动时递归扫描并重新标记所有文件，导致严重的挂载超时。 自 v1.27 起，通过 Mount Options 优化（Beta），可以直接在挂载参数中指定 SELinux 标签，免去递归扫描。
* **调优 Kubelet QPS 限制**：当单节点上高并发启动大量 Pod 时，Kubelet 会因为默认的 API 请求限制（先前默认 `QPS=5`，`Burst=10`）而向 API Server 发起排队。 在 v1.27 中，Kubelet 的默认并发限制被放大了 10 倍，有效消除了高密度部署场景下的流控瓶颈。

## 六、异构计算（GPU）管理与大模型数据加载加速

随着大模型时代的到来，异构计算的管理和海量数据集的加载速度成为了制约集群启动效率的最新瓶颈。

### 1. 异构资源管理演进：从 Device Plugin 到 DRA

为了彻底解决传统设备插件的缺陷，Kubernetes 社区推出了 **DRA（Dynamic Resource Allocation，动态资源分配，KEP-3063）**。

* **DRA 的优势**：将设备管理上升到一等公民，提供类似于 PV/PVC 的 ResourceClaim 声明模型，支持多设备参数灵活定义、网络附加 GPU（Network-Attached GPUs）、复杂网络拓扑感知以及灵活的设备共享策略。
* **当前的挑战**：由于调度需要高频读写 API Server 获取 Claim 状态，在大规模高并发调度时会略微增加调度器的时延，且其 YAML 配置复杂度显著增加。

### 2. 壁仞科技的自定义实践（虚拟设备 + 自定义调度器）

在社区 DRA 尚未完全成熟和普及前，壁仞科技通过“Fake Device + 拓扑感知调度器”方案实现了极致的异构计算管理：

1. **节点 Agent 伪装**：在节点本地运行 Agent，向 Kubelet 的 Device Plugin 注册一组“虚假的 GPU 设备”（Fake Device）。 这些 Fake Device 在底层其实只是无实质意义的软链接（Symlink）或空心设备文件。 Kubelet 误以为本地拥有充足的异构设备，从而直接放行 Pod 的调度申请。
2. **自定义调度器（Custom Scheduler）拓扑决策**：调度器拥有集群全局的物理 GPU 拓扑视图。 在调度阶段，它会根据卡间 NVLink 带宽、PCIe 拓扑及共享状态做出最优的分配决策，并将具体的绑定信息（如将几号物理卡分配给该 Pod）写入自定义的 `GPUBinding` 资源中。
3. **设备映射动态链接**：当 Kubelet 本地准备拉起容器并调用 `PreStartContainer` 时，节点 Agent 拦截该调用，读取 `GPUBinding`，在底层将真正的物理 GPU 设备文件建立软链接，直接替换掉容器内部的 Fake Device。
4. 这套方案在不修改 Kubernetes 核心代码的前提下，完美实现了 GPU 的拓扑感知分配、跨 Pod 共享、切分以及精细化卡指定。

### 3. AI 训练数据集加载加速

大模型训练在启动时需要加载数 TB 甚至数十 TB 的训练数据集。 若直接通过网络从远程 HDFS 或 Ceph 中读取，会导致启动初期的 I/O 吞吐极低。

**加速数据加载的优化闭环**：

* **一阶段（Prepare）**：在 Pod 调度成功后，前置的 Data Agent 开始异步预热，提前将所需的分块数据集拉取并缓存在节点本地的 NVMe SSD（Disk）中。
* **二阶段（Memory Copy）**：将高频使用的热点训练数据，通过节点大内存直接载入 Page Cache（Memory）。
* **三阶段（GPU Copy）**：GPU 运行时直接从本地高带宽内存或本地 SSD 中读取数据，实现高吞吐训练，避开分布式文件系统的网络带宽限制。
* **四阶段（LRU Cache Eviction）**：本地 Data Agent 实时监控节点的磁盘空间，当训练结束或空间不足时，自动基于 LRU 淘汰算法清理陈旧的数据集缓存，确保本地磁盘健康。

## 七、可观测性（Observability）

在进行任何性能调优前，完备的数据指标是唯一的事实依据。

### 1. 内核级深链追踪

在大规模、极端延迟调优场景下，可利用 Linux BCC / BPF 调试工具（如 `execsnoop` 监听进程创建，`biosnoop` 监听底层磁盘 I/O 延迟）定位是由于系统调用卡顿还是宿主机硬件性能瓶颈导致。

### 2. Kubelet 结构化启动日志

自 v1.26 起，Kubelet 提供了极其详尽的结构化 Pod 启动追踪日志。 当 Pod 启动完成后，Kubelet 会在日志中输出以下关键时间轴：

```json
{
  "observed_pod_startup_duration": "pod_start_sli_duration_seconds",
  "podCreationTimestamp": "2022-12-30 15:33:00",
  "firstObservedPulling": "2022-12-30 15:33:05",
  "lastObservedFinishedPulling": "2022-12-30 15:33:10",
  "observedRunningTime": "2022-12-30 15:33:15"
}
```

通过这些日志，你可以清晰地得出以下结论：

* **镜像拉取耗时** = `lastObservedFinishedPulling` - `firstObservedPulling` = 5 秒
* **Sandbox 及容器配置耗时** = `observedRunningTime` - `lastObservedFinishedPulling` = 5 秒

### 3. Prometheus 指标监控

Kubelet 会将上述统计上报为标准的直方图指标：`pod_start_sli_duration_seconds`。

```prometheus
# Prometheus 直方图部分数据示例：
pod_start_sli_duration_seconds_bucket{le="10"} 120
pod_start_sli_duration_seconds_bucket{le="30"} 145
pod_start_sli_duration_seconds_bucket{le="45"} 146
```

通过观察分位数（如 P99、P95），运维团队可以敏锐地发觉是否有某些特定类型的 Pod（或运行在特定节点上的 Pod）出现了异常的长尾延迟，并基于该指标在 Grafana 上组建监控大盘与告警通路，从而保障集群的整体性能。


# 美文

自古表白多白表，从来情书难书情。笑谈年少多少年，常与生人道人生。

{% hint style="warning" %}
仅是转载收藏，无意冒犯版权。
{% endhint %}


# 一个和十万个地球

刘慈欣

与其它动物相比，人类的婴儿是十分脆弱的，小马出生后十分钟就能自己直立行走，而人类的婴儿要在摇篮里呆相当长的时间，这期间如果没有外界的悉心照顾，他们不可能生存下去，凭自己的力量，人永远无法走出摇篮。产生这种现象的原因是进化的需要，人的大脑体积较大，充分发育后则难以出生，只有提前生出来，也就是说，所有的人类婴儿都是早产儿。

如果把人类文明的整体看做一个婴儿的话，那么也是一个早产儿。文明的发展速度远快于自然的进化，人类实际上是用原始人的大脑和身体进入现代文明的。那么就有这样一个可怕的问题：如果没有外界的照顾，人类文明这个婴儿是否也永远无力走出自己的摇篮？

现在看来有这个可能。

在遥远的未来，当人们回顾上世纪中叶至今的历史时，这期间发生的所有惊天动地的大事都将被时间磨的平淡无奇，只有两件现在被我们忽视的事情将变得越来越重要：一、人类迈出了走出摇篮的第一步；二、人类又收回了迈出的脚步。这两件事的重要性怎样评价都不为过，加加林飞入太空的 1961 年可能代替耶稣诞生的那一年而成为人类元年，而阿波罗登月后太空探索的衰退，将给人类留下比被逐出伊甸园更惨痛的创伤。

上世纪五十年代末至七十年代初将当做黄金时代而记忆，在发射第一颗人造卫星后仅三年多，第一名宇航员就进入太空，其后仅七年多，人类就登上了月球。当时，人们被远大的目标所激奋，认为再有十年左右人类将登上火星，而抵达木星轨道登上木卫二也不是遥远的事。早在这之前，就诞生了豪气冲天的猎户座计划，用不断爆炸的原子弹驱动飞船，可以一次将几十名宇航员送上外行星。

但很快，阿波罗登月因资金中断，取消了剩下的飞行。以后，人类的太空探索就像一块在地球重力场中抛起的石头，达到顶点短暂停留后急剧下坠。阿波罗十七号最后一次登月的 1972 年 12 月是一个重要的转折点，其后，虽然仍有空间站和航天飞机，有越来越多的各类人造卫星和它们所带来的经济效益，有飞向地外行星的探测器，但人类太空事业的性质已经悄然发生了改变，太空探索的目光由星空转向地面。阿波罗十七号之前的太空飞行是人类走出摇篮的努力，之后则是为了在摇蓝中过的更舒适些。太空事业纳入了经济轨道，产出必须大于投入，开拓的豪情代之以商人的精明，人类心中的翅膀折断了。

其实，回头看看，人类曾经真的想要走出摇蓝吗？上世纪中叶的太空探索热潮背后的驱动力是冷战，是对对手的恐惧和超越的愿望，是一种显示力量的政治广告，人类其实从来没有真心地把太空当做未来的家园。

现在，月球重新变成了没有人迹的荒凉世界，俄罗斯和美国的行星载人飞行计划先后变为泡影，欧洲探索太阳系的“曙光计划”也被搁置看不到一点曙光。在航天飞机退役之后，曾经踏足月球的美国人甚至在相当长的时间里失去了把人送上近地轨道的能力。

为什么会这样，我们能想到的原因无非是技术和经济两方面。

首先看技术原因：不可否认，人类目前不具备在太阳系内进行大规模太空开发的技术。在太空航行最基本最关键的推进技术上，人类目前只处于化学推进阶段，而大规模行星际航行则需要核动力推进，目前的技术距此还有相当的距离，核动力的火箭和飞船还只是科幻小说中的东西。

再看经济原因：以现有的技术，把有效载荷送入近地轨道，耗资相当于同样重量的黄金；而送到月球和其它行星，所需资金则十倍甚至百倍增长，而在太空开发产业化之前，所有这些投入只得到很小的回报，比如阿波罗登月工程耗资 260 亿美元，相当于现在的一千多亿美元，只得到两吨多的月球石块（当然，登月工程的技术成果在其后的民用化过程中产生了巨大的效益，但这些效益无法量化，不可能做为决策时考虑的决定性因素。）

由上所述，太空开发无论在技术上还是在经济上都是巨大的冒险，把太空看做人类新的家园，把人类的未来寄托在这样一个大冒险上，这在政治上是无法被接受的。

以上的理由论据坚实，似乎不可辩驳，也就决定了目前人类的太空政策和其所导致的太空事业的衰落。

但让我们考察一下人类目前正在全力投入、并把其看地球文明未来生存的惟一出路的一项宏大的事业：环境保护。

从技术层面上看，太空航行和环保在人们头脑中的色彩是不一样的，前者是剧烈的、高速的和冒险的，意味着尖端高技术；后者则是一种温和的绿色的公益活动，自然有技术在其中，但其难度在印象中与前者相差甚远。

但这只是印象而已，真实的情况是：要达到人类现有的环境保护的目标，所需的技术比起大规模行星际航行要难的多。

在认知层面上，要想保护环境首先要认识它，要从全球尺度上理解它的规律，而地球的生态系统是一个极其复杂的系统，虽然各学科对其细节有了巨量的研究和了解，但在全球的整体尺度上，目前人类无论从基础科学还是从应用科学层面上都没有掌握它的规律，对于天气系统的运行、大规模生物群落的变化和相互关系等，人类科学所能知道的都很有限。以全球变暖为例，与铺天盖地众口一词的宣传不同，地球气候是否真的在变暖，如果是，变暖是否与人类活动有关？对这两项至关重要的问题，科学研究目前都无定论，所以遏制全球变暖更像一项政治运动。可以毫不夸张地说：人类对地球表面，还不如对月球表面了解的多，可能很快，也不如对火星表面了解的多。

在行动层面上，目前环境保护所需要的技术，比如用可再生能源代替化石能源、对工业废物和城市垃圾的处理和循环使用，对生物多样性的保护、对森林植被的保护和恢复等，都涉及到复杂的技术，其中相当一部分不比太阳系内的行星际航行技术容易多少。

但环境保护在技术上的挑战主要还不在于此。现在，全球性的战争和动乱已经远去，人类社会进入持续的和平发展时期，特别是第三世界和不发达地区，发展的速度前所未有，这些高速发展的区域有着同一个目标：达到西方发达国家的经济水平，过他们那样的现代化的舒适生活。现在看来，这并非一个遥不可及的目标，照目前的发展速度，只需再有半个世纪，大部分的不发达地区，包括中国和巴西这样的第三世界国家，在经济上就能够赶上西方。

但人们忽略了这样一个事实：如果全人类都像欧美发达国家那样生活，所消耗的资源需要四个半地球才够。

在这种情况下，如果要达到环境保护的最终目标，维持地球生态免于崩溃，制止目前正在发生的比白垩纪大灭绝速度更快的物种灭绝，仅靠自律来减少污染，仅靠节能减排是远远不够的，即使哥本哈根会议的全部目标都已实现，地球生态环境仍像冰洋上的泰坦尼克号一样在沉下去。

惟一的希望是停止发展。但发展是不可遏止的，在一些国家和地区的人们躺在现代文明舒适的躺椅上悠哉乐哉时，让地球上其余的部分停留在农村业化社会的落后与贫穷中，这违反的人类的基本价值观，在政治上也是完全不可行的。

再考察另外一种可能性：非人类因素带来的环境巨变。地球环境一直处于波动之中，只是人类文明史太短暂人们没能觉察而已。每一次波动中，地球环境整体都会发生巨变，可能变的完全不适合人类生存。比如最近的一次冰期在一万年前才结束，如果那样的冰期再来一次，各大陆将被冰雪覆盖，现有的全球农业将崩溃，对拥有巨量人口的现代化社会而言将是灭顶之灾。而这样的环境巨变从长远看来几乎是必然要发生的，甚至有很大的可能就在不太遥远的未来出现，对这样的环境变化，现有的环保手段只是杯水车薪。

人类文明要想在人为的或自然的环境变化中长期生存下去，只能把环境保护行为由被动变主动，人工整体性地调整和改变地球环境。比如缓解温室效应，人们提出了多种方案，包括在海洋上建立大量的巨型太阳能蒸发站，把海水蒸发后喷入高空以增加云量；在太阳和地球间的拉格朗日点，给地球建造一面面积达 300 万平方公里的遮阳伞。。。。。。等等，这些工程无一不是史无前例的超级工程，其规模之大，如上帝的手笔，所涉及的技术也都是地地道道的在科幻中才有的超级技术，其难度远大于太阳系内的行星际航行。

除了技术上的难度，从经济层面上看环境保护，我们发现它与太空开发也十分相似：都需投入巨量的资金，在初期也都没有明显的经济回报。

但人类对环保的投入与对太空开发的投入相比，大的不成比例。以中国为例，十二五规划中计划投入环境保护的资金为三万多亿人民币，但对太空探索，只计划投入三百亿左右。世界其它国家的情况也相差不多。

太阳系中有着巨量的资源，在八大行星上，在小行星带中，人类生存和发展需要的资源，从水到金属到核聚变燃料，应有尽有，按地球可以最终养活一千亿人口计算，那么整个太阳系中的资源总量可以养活十万个地球的人口。

现在，我们看到了这样一个事实：人类放弃了太空中的十万个地球，只打算在这一个地球上生存下去，而他们生存的手段是环保，一项与太空开拓同样艰巨同样冒险的事业。

同环保一样，太空开发与技术进步是互动关系，太空开发会促进技术进步，波罗工程之前美国并不具备登月需要的技术，相当一部分技术是在工程的进行中开发的。核裂变技术在地球上已成为现实，实现太空核推进并不存在不可逾越的障碍；可控核聚变虽然还未实现，但只存在技术障碍而不是理论障碍。

我们要看到这样一个事实：四十多年前登月飞船上的导航和控制计算机，其功能只相当于现在 IPHONE4 的千分之一。

太空开拓与已经过去的大航海时代很相似，同样是远航到一片未知的世界，去开拓人类的生存空间，开拓一个更好的生活。大航海时代的开始是哥伦布发现新大陆，哥伦布的航行在当时得到了西班牙伊莎贝拉一世女王的支持 (更确切地说是是卡斯提亚尔王国的女王，当时独立的西班牙并不存在)，女王自己也难以供起这个船队，据说她把自己的首饰都典当了，然后供给哥伦布远航。现在的事实证明，这是最明智的一笔风险投资，以至于有人说世界历史是从 1500 年开始的，因为到那个时候人们才知道整个世界的全貌。

现在，人类正处在第二次大航海时代的前夜。我们现在甚至比哥伦布要有利得多，因为哥伦布看不见他要找的新大陆，他在大西洋上航行了几天之后还没有见到陆地，这个时候他的内心肯定是充满了犹豫彷徨。而我们要探测的新世界抬头就能看到，但是现在没有人来出这笔钱。

也许，人类文明做为一个整体，就像人类的个体婴儿一样，在没有父母帮助的情况下，真的永远无法走出摇篮。

但从宇宙角度看，地球文明是没有父母的，人类是宇宙的孤儿，我们真的要好自为之了。


# 短篇


# 爱

作者：张爱玲

这是真的。

有个村庄的小康之家的女孩子，生得美，有许多人来做媒，但都没有说成。那年她不过十五六岁吧，是春天的晚上，她立在后门口，手扶着桃树。她记得她穿的是一件月白的衫子。对门住的年轻人同她见过面，可是从来没有打过招呼的，他走了过来。离得不远，站定了，轻轻的说了一声：“噢，你也在这里吗？”她没有说什么，他也没有再说什么，站了一会，各自走开了。

就这样就完了。

后来这女人被亲眷拐子卖到他乡外县去作妻，又几次三番地被转卖，经过无数的惊险的风波，老了的时候她还记得从前那一回事，常常说起，在那春天的晚上，在后门口的桃树下，那年轻人。

于千万人之中遇见你所遇见的人，于千万年之中，时间的无涯的荒野里，没有早一步，也没有晚一步，刚巧赶上了，那也没有别的话可说，惟有轻轻地问一声：“噢，你也在这里吗？”


# 弟弟

作者：张爱玲

我弟弟生得很美而我一点都不。从小我们家里谁都惋惜着，因为那样的小嘴，大眼睛与长睫毛，生在男孩子的脸上，简直是白糟蹋了，长辈就问他：“你把眼睫毛借我好不好？明天就还你。”然而他总是一口回绝了。有一次，大家说起某人的太太真漂亮，他问道：“有我好看么？”大家常常取笑他的虚荣心。

他妒忌我画的图，趁没人的时侯拿来撕了或是涂上两道黑杠子。我能够想象他心理上感受的压迫。我比他大一岁，比他会说话，比他身体好，我能吃的他不能吃，我能做的他不能做。

一同玩的时侯，总是我出主意。我们是“金家庄”上能征惯战的两员骁将，我叫月红，他叫杏红，我使一口宝剑，他使两只铜锤，还有许许多多虚拟的伙伴。开幕的时侯永远是黄昏，金大妈在公众的厨房里咚咚乇菜，大家饱餐战饭趁着月色翻过山头去攻打蛮人。路上偶而杀两头老虎，动行老虎蛋，那是巴斗大的锦毛球，剖开来像白煮鸡蛋，可是蛋黄是圆的。我弟弟常常不听我的调派，因而争吵起来，他是“既不能命，又不受令”的，然而他实在是秀美可爱，有时侯我也让他编个故事：一个旅行的人为老虎追赶着，赶着，赶着，泼风似的跑，后头呜呜赶着——没等他说完，我已经笑倒了，在他肋上吻一下，把他当个小玩意。

有了后母之后，我住读的时侯多，难得回家，也不知道我弟弟过去时是何等样的生活。有一次放假，看见他，吃了一惊。他变得高而瘦，穿一件不甚干净的蓝布罩衫，租了许多连环图画来看。我自已那时侯正在读穆时英的，《南北极》与巴金的《灭亡》，认为他的口胃大有纠正的必要，然而他只晃一晃就不见了。大家纷纷告诉我他的劣迹，逃学，忤逆，没志气。我比谁都气愤，附和着众人，如此激烈地诋毁他，他们反而倒过来劝我了。

后来在饭桌上，为了一点小事，我父亲打了他一个嘴巴子。我大大地一震，把饭碗挡住了脸，眼泪往下直淌。我后母笑了起来道：“咦，你哭什么？又不是说你！你瞧，他没哭，你倒哭了！”我丢下了碗冲到隔壁的浴室里去，闩上了门，无声地抽噎着。我立在镜子前面，看我自已的掣动的脸，看着泪滔滔流下来，像电影里的特写。我咬着牙说：“我要报仇。有一天我要报仇。”

浴室的玻璃窗临着阳台，拍的一声，一只皮球蹦到玻璃上，又弹回去去了。我弟弟在阳台上踢球。他已经忘了那回事了。这一类的事，他是惯了的。我没有再哭，只感到一陈寒冷的悲哀。


# 暗途

作者：许地山

“我的朋友，且等一等，待我为你点着灯，才走。”

吾威听见他的朋友这样说，便笑道：“哈哈，均哥，你以我为女人么？女人在夜间走路才要用火；男子，又何必呢？不用张罗，我空手回去罢——省得以后还要给你送灯回来。”

吾威的村庄和均哥所住的地方隔着几重山，路途崎岖得很厉害。若是夜间要走那条路，无论是谁，都得带灯。所以均哥一定不让他暗中摸索回去。

均哥说：“你还是带灯好。这样的天气，又没有一点月影，在山中，难保没有危险。”

吾威说：“若想起危险，我就回去不成了……”

“那么，你今晚上就住在我这里，如何？”

“不，我总得回去，因为我的父亲和妻子都在那边等着我呢。”

“你这个人，太过执拗了。没有灯，怎么去呢？”均哥一面说，一面把点着的灯切切地递给他；他仍是坚辞不受。

他说：“若是你定要叫我带着灯走，那让我更不敢走。”

“怎么呢？”

“满山都没有光，若是我提着灯走，也不过是照得三两步远，且要累得满山的昆虫都不安。若凑巧遇见长蛇也冲着火光走来，可又怎办呢？再说，这一点的光可以把那照不着的地方越显得危险，越能使我害怕。在半途中，灯一熄灭，那就更不好办了。不如我空着手走，初时虽觉得有些妨碍，不多一会，什么都可以在幽暗中辨别一点。”

他说完，就出门。均哥还把灯提在手里，眼看着他向密林中那条小路穿进去，才摇摇头说：“天下竟有这样怪人！”

吾威在暗途中走着，耳边虽常听见飞虫、野兽的声音，然而他一点害怕也没有。在蔓草中，时常飞些萤火出来，光虽不大，可也够了。他自己说：“这是均哥想不到，也是他所不能为我点的灯。”

那晚上他没有跌倒，也没有遇见毒虫野兽，安然地到他家里。


# 噩梦

作者：蔡澜

“绑安全带！”

一上车，女人已经命令。

驾了那么多年车子，男人怎么不会做这件事？但还是客气地：“呀，差点忘了。”

出了门口，男人向左转。

“转右！”女人又命令。

“昨天这个时候那条路塞车。”男人解释，“今天不如换一条路走吧。”

太太显然地对这个自作主张的部下不满，但不出声，心中想：“嘿嘿，要是另一条路也塞车，就要你好看！”

有那么巧就那么巧，其他人也聪明地转道，变成一条长龙。

“转头！昨天塞车，并不代表今天也塞车呀！”女人说，“要是你听我的话做，不是没事吗？”

“是，老婆大人。”男人是乖乖地依着女人指定的方向走去。

当然，又是一条长龙，繁忙时间，哪有不塞车的道理？但是女人说：“这条龙比刚才那条短得多！”

“你看得出哪一条龙长，哪一条龙短，这可出奇了。”男人想讲，但忍了下来。

闲来无事，两者又无对话，男人打开收音机听新闻。

“每天都是波斯尼亚战事，乌干达难民，有什么好听？”女人伸手一按，录音带播出邓丽君的旧歌。

后面有辆的士一直在按喇叭。

女人转头，狠狠地瞪了的士司机一眼，大叫道：“响什么？赶着去奔丧啊？”

“那些年轻人血气方刚，听到了什么事情都做得出的。”男人低声下气地。

“怕什么？”女的理直气壮，说完就要按下玻璃窗，伸头出去咒骂。

“别……别……”男人慌忙阻止。

好在的士司机已经不耐烦，越过双白线，开车往前去。

“跟着他走！跟着他走！”女人再次命令，“老在这里等着，什么时候才能赶到？”

“那是犯法的呀！警察抓到会抄牌的呀！”男人抗议。

“人家怎么不怕？”女的以轻视的目光看着男人，“要抓也是抓他去，你……你……”

男人在女人还没讲到“没种”这两个字之前，战战兢兢地把车驶出双白线，超过别人的车子。

忽然迎面来了几辆车，喇叭声大作，男人即刻把车子闪到一边，险过剃头地避开，捏了一把冷汗。

打躬作揖地要求排长龙的司机让一让，才能将车子驾进去，但是他们不买账，一车跟一车地贴得紧紧的，绝对不腾出一点空间。

“冲呀！”女人斩钉截铁地命令。

男人即刻照做。

这次，迎面来的是一辆运货柜的大卡车，嘭的一声巨响，撞个正着，奔驰的车头已扁，冒出浓烟。

女人的第一个反应不是看丈夫有没有受伤，她尖叫：“要是你听我的话做，不是没事吗？”

货车中跳出两名彪形大汉，直往车子走来，男人心中叫苦：“完了，这次完了！”

嗡嗡巨响，骑白色大型电单车的交通警及时赶到，男人好像得到救星，跳出车子，紧紧地把他抱住。

交通警大力地把男人一推，大喊：“告多你一条同性侵犯罪！”

“救命！”男人哀求。

交通警慈悲心发，安慰地：“别怕，有我在，那两个男人不会打你的。”

“我不是怕那两个大汉！”男的已经歇斯底里，“我怕的是坐在车里的那个女人！”

“你说什么？”太太下车狂吼冲前。

男的落荒而逃。

“喂！”交通警在他身后大叫，“你的奔驰车不要了吗？”

“车子！老婆！”男的边逃边喊，“都送给你！”

交通警欲跳上电单车追来，但给其他车辆阻着。男的跑了几条街，抬头一看，是结婚前的女朋友住的地方。

男人直奔进女朋友的怀抱：“快点收拾行李，我自由了，我们马上乘国泰航空到欧洲去旅行！”

女的大喜，抱着他吻了又吻。正当男的觉得一生幸福，由此开始的时候，女的说：“不如坐维珍航空吧。”

“为什么？我一向惯坐国泰的。”男的说。

女的回答：“听我的话做，没事。”

咦？这句话在什么地方听过？男人觉察后鸡皮疙瘩竖起，大喊：“不，不！”

冲出门，男人再跑几条街，跑回妈妈家里，直奔母亲的怀抱：“我再也受不了所有的女人。”

世上只有妈妈好。妈妈抱着哭泣的儿子，摸摸他的头：“老早就说那个女人不适合你的了。要是你听我的话做，不是没事吗？”


# 想象

作者：凯 · 杰罗姆

记得那天，我到大英博物馆去查阅有关接触性枯草热的治疗情况，我猜我大概得了这种病。

取下一本医书，我一口气读完了所有的相关内容。然后，我懒散地胡乱翻着书页，粗略地研究起疾病来。没等看完一连串的病症征兆，我便意识到自己恰恰得了这种病。

我坐在那里呆呆地发愣，陷入绝望之中。过了好一会儿，我又拿起那本书，翻了起来。翻到伤寒——仔细看了它的各种症状，我发现我又得了伤寒，想必我得此病已经好几个月了，竟然还茫然不知。不知我还患有其它什么疾病？

翻到舞蹈病，我发现，正如我预先料想的那样，我也患有这种疾病。我开始对自己的病情产生了兴趣，并决定一查到底。我开始按字母顺序逐个检查——翻到疟疾，我知道自己已经出现了疟疾的某些症状，两个星期后进入急性发作期；翻到肾小球肾炎，我心中稍微感到一丝安慰——我得的只是其中较轻一种，就目前状况而言，我还可以活上几年。此外，我还染上了霍乱，并伴有严重的并发症。而白喉对我来说似乎是与生俱来的疾病。我不厌其烦地按照 26 个字母统统检查了一遍，结果发现，惟一没有得上的疾病就是髌前囊炎。

起初，我对此颇有些伤感，心中似有几分失落。为什么我没有得上髌前囊炎呢？不过，过了一会儿，我的心渐渐变得开朗起来。我想，从药理学讲，我不是已经得了其它各种常见的疾病了吗？没有得上髌前囊炎那就算了吧！反正痛风已经处于恶性晚期了。

我陷入了沉思。我想，从医学角度来说我是一个非常有趣的病例，对于医学院学生来说，我更是一个极为难得的病例！如果学生们有了我，他们也就无须到医院去实习了——我就是他们的“实习医院”。他们所要做的就是在我身上研究研究，然后就可以拿到他们的毕业文凭了。

我不知道自己究竟还能活多久，我得做一番自我检查。我摸了摸自己的脉搏。起初，我什么也摸不着，不久那脉搏又突然跳了起来。我掏出怀表，测算脉搏的次数，大概每分钟 147 次。我又摸了摸心脏，竟然发现它已经停止跳动了！后来，我渐渐意识到我的心脏还在那里，想必也没有停止跳动。只是我对此无法解释而已。我看了看自己的舌头——我尽量把舌头伸得长长的，闭上一只眼睛，用另一只眼来检查。我只能看见自己的舌尖，得到的惟一收获是：我比以前更加确信我得了猩红热。

走进阅览室的时候，我是一个健康快乐的人，出来的时候我变成了拖着衰弱病躯的重症病人。

于是，我去看了医生。他是我的一位好友，他摸了摸我的脉搏，又看了看我的舌头，后来不知怎么地谈起了天气。之后他问：“你究竟哪里不舒服？”

我说：“老兄，我不会告诉你我得了什么病，让你白费那么多时间。不过，我可以告诉你我没有得什么病——我没有得髌前囊炎。除此之外，什么病我都有。”

我还把自己是如何发现这些疾病的过程如实告诉了他。

随后他解开我的衣服，紧握着我的一只手腕，在我胸部一阵乱敲；又把脑门贴到我的身上。最后他坐了下来，开了一个处方，然后把它叠起来递给我。我接了过来，随手揣进衣兜里，走了出去。

我径直来到一家最近的药店，药剂师看了看处方，又将它退了回来。

他说他不收这种处方。

“你不是药剂师吗？”我问。

“我是药剂师。如果我经营一个合作商店兼营家庭旅馆的话，我倒是可以为你效劳。可我只是一个药剂师，我无能为力。”

我看了看那处方，上面写道：“一磅牛排，外加一品脱苦啤酒，每隔 6 小时服用一次；每天早晨散步 10 英里；每天晚上 11 点上床睡觉。此外，不要满脑子都装些你不明白的东西。”


# 底线

作者：冯骥才

一次，一位在江南开锁厂的老板说他的买卖很兴旺，日进斗金，很快要上市了。我问他何以如此发达？

他答曰：“现在的人富了，有钱有物，自然要加锁买锁；再有，我的锁科技含量高，一般技术很难打开，而且不断技术更新，所以市场总在我手里。”

我笑道：“我的一位好朋友说世界上他最不喜欢的东西就是锁，因为锁是对人不信任，是用来防人的。”

锁厂老板眉毛一挑说：“不防人防谁？我赚的就是防人的钱。你以为这世上真有夜不闭户的地方吗？”

我说：“五十年代真有。七十年代我住在一座房子的顶楼上，门上只有个挂钩，没锁，白天上班把门一关钩一挂，从来没被人偷过。”

锁厂老板说：“那是什么时候，早没影儿了，不信你不锁门试试。”

我笑了笑没再说，我信他的话。我承认，一个物欲的时代和一个非物欲的时代，人的底线是不同的。社会的底线也在下降。所谓社会底线下降，就是容忍度的放宽。原先看不惯的，现在睁一眼闭一眼了；原先不能接受的，现在不接受也存在了。在商业博弈中，谎话欺骗全成了“智慧”；在社会利益竞争中，损人利己成了普遍的可以获利的现实；诚信有时非但无从兑现，甚至成为一种商业的吆喝或陷阱。在这样的社会生态中，人的底线不知不觉在下降。

可是这底线就像江河的水线，水有一定高度，船好行驶，人好游泳。如果有一天降到了底儿，大家就一起陷在烂泥里。我们连自己是脏是净是谁也不知道了。

所以，人总得有自己做人做事的底线。其实这底线原本是十分清楚的。比如人不能“见利忘义”“卖友求荣”“卖国求荣”“乘人之危”，不能“虐待父母”“以强凌弱”“恩将仇报”“落井投石”，还有“不义之财君莫取”“朋友妻不可欺”等等。

这个古来世人皆知的底线，也是处世为人的标准，似乎已被全线突破了。

底线是无形地存在于两个地方。一在社会中，一在每个人心里。如果人们都降低自己的底线，社会的底线一定下降。社会失去共同遵守的底线，世道人伦一定败坏；如果人人守住底线，社会便拥有一条美丽的水准线——文明。因此说，守住底线，既为了成全社会，也是成全自己。

然而，这两个底线又相互影响。关键是在你的底线有时碰到低于你的底线时，你是降下自己的底线，随波逐流；还是坚守自己，洁身自好，坚持一己做人做事的原则？有人说，在物欲和功利的社会里，这底线是脆弱的。依我看，社会的底线是脆弱的，人的底线依旧可以坚强，牢固不破。

底线是人的自我基准，道德的基准，处世为人的基准。

人的自信是建立在底线上的。没有底线，一定会是一塌糊涂的失败的自我，乃至失败的人生。有底线，起码在“人”的层面上，获得了成功的自我与成功的人生。


# 疯人

作者：纪伯伦

我在精神病院的花园里碰见了一个年轻人，他看上去面色苍白，人很可爱，富有奇想。我在他旁边的长凳上坐下，我问：“你为什么会在这儿呢？”

他惊讶地望着我说：“这是一个不礼貌的问题，不过我会回答你。我的父亲想把我变成他的复制品，我的叔叔也指望我跟他一样。我的母亲希望我像她那大名鼎鼎的父亲，而我的姐姐以为她那航海的丈夫是个十全十美的榜样，要我学他。我的哥哥想让我跟他一样，做个好的运动员。”

“我的老师依然如此，要我成为哲学老师、音乐老师、逻辑学老师，他们也都很坚决，每个人不过是要我成为他们镜子里的影子。”

“因此，我来到了这个地方。我发现在这儿我的神志更正常点。至少，我能做回我自己。”

突然他转过来对我说：“告诉我，你也是被教育和忠告赶到这个地方的吗？”

我回答道：“不，我只是个访客。”

然后他回答道：“噢，你是住在精神病院墙那边的病人。”


# 雪兔

作者：郑渊洁

路路是一只黑兔。他恨自己的肤色。

森林里只有路路一只黑兔，白兔们不跟他玩，就因为他肤色黑，路路从小就喜欢一只叫冉冉的白兔。冉冉性格温柔，走起路来姿态特别好看。路路经常躲在大树后边看她。有一天，路路在草丛里碰见了冉冉。

“你好。”路路心使劲跳。

“……”冉冉见是黑兔，没吭声。从小爸爸就告诉她，白兔比黑兔高贵。

路路给冉冉让开路。冉冉头也不回地走了。

路路连做梦都想把自己的肤色变成白色，不为别的，就为能同冉冉说几句话。可他清楚这是不可能的事。没有希望的生活是痛苦的。

冬天到了。一天夜里，天上飘起鹅毛大雪，转眼间就把山林染白了。

睡在草丛里的路路的身上挂满了雪花。清晨，路路惊喜地发现，自己变成了白兔。路路兴奋，虽然他知道太阳一出来，身上的雪就会融化，但他只要能同冉冉说上几句话，他就满足了，路路祈祷太阳晚些出来。

路路小心翼翼地朝白兔居住的地方走去，他生怕碰落了身上的雪花。

上帝会安排。路路没走多远，就看见冉冉在两棵大树之间玩雪。

“你好。”路路说。

“你好！”冉冉见是一只白兔，友好地说。

“咱们一块儿玩行吗？”路路谨慎地试探。

“当然可以。”冉冉说，“我怎么没见过你？”

“我……我是从别的森林来的。”路路不得不撒谎。他认为自己是在撒真诚的谎。不坏。

冉冉和路路一边玩一边聊天。冉冉真喜欢路路，喜欢他的性格，喜欢他的幽默。

路路更是感到甜美，他认识到自己并不比白兔差，这从冉冉兴奋的程度上就能判断出来。

太阳终于无情地从山后露出了通红的脸庞，树枝上的雪花开始变成水珠坠落进泥土。

路路明白自己的真面目马上就要暴露了，他不愿破坏这美好的场面。

“再见了！”路路说。

“再玩一会儿不行吗？”冉冉央求。

“我还有事，以后来玩。”路路又说谎了。这回是神圣的谎。

“我等你。”冉冉依依不舍地说。

路路走了。

几天后，路路又碰见了冉冉。

“你好！”路路情不自禁地问。

“……”冉冉一看是黑兔，不理他。

路路心里感到凄凉。

从此，路路天天盼着下雪，可整整一个冬天再没下第二场雪。

后来路路听说，冉冉失踪了。有人说她去别的森林找一只叫路路的白兔，也有人说她在半路上遇到了狼的袭击。

路路恨那场大雪。


# 夺妻

作者：达里姆·齐特里

卡尔下了车，走进朋友家宽敞明亮的宴会厅。今晚这里将有一个热闹的聚会。

卡尔是一位有钱的商人，30 多岁仍孑然一身，正打算物色合适的人选成家。一进朋友家，卡尔的目光就被一位迷人的姑娘所吸引。

随后的活动中，卡尔心中再无他物。他寻找一切机会与那姑娘接近。她叫比玛，在一家公司做秘书。她对卡尔似乎也很有好感。

两人谈兴正浓时，聚会却已接近尾声。于是，卡尔主动提出送比玛回家，她欣然同意了。

很快，卡尔的车停在一所幽静的寓所前，两人依依不舍地道别。让卡尔略略有些失望的是，比玛并没请他上楼坐坐。

随着时间的推移，他们开始不断约会，一切都进展顺利，卡尔非常高兴终于找到了一个意中人。

但有一天，卡尔在与比玛共进午餐时，发现她神情有些抑郁。卡尔关切地问："怎么回事，比玛，有什么需要我帮忙吗？"

比玛未作回答，眼泪却止不住地流了下来。卡尔心都痛了："亲爱的比玛，我想娶你为妻，为你分忧。你愿意吗？"

可令卡尔窘迫的是，比玛先是泪珠滚滚，继而失声痛哭起来，引来饭店里不少顾客好奇的目光。后来，比玛终于平静下来，说："卡尔，很遗憾，我已经结婚，我已属于别人。他是不会同意跟我离婚的。"

在卡尔惊愕的目光中，她拎起手包，哭着离开饭店。打那以后，卡尔始终心神不定，他放不下比玛，常常想起他们相处的甜蜜时光，他们本就该是天造地设的一对！于是，他决定采取极端行动。

卡尔先作了一番周密调查，然后雇了个杀手，准备把比玛的丈夫除掉。杀手临行前，卡尔还一再提醒他行动要干净利索，以免被人发现。

计划能否顺利实施？那天晚上，卡尔焦虑地在屋中踱来踱去。终于，电话铃响了。

"喂！"他迅速抓起话筒。

"老板，您交代的任务完成了。"

"很好！"卡尔说，"一切是否顺利？"

"是的，嗯，不过……"

"不过什么？"卡尔心脏狂跳。

"不过，当我离开时，被一个女人发现了。"

"你这个傻瓜！我一再提醒你要小心。"

"没问题，老板，"对方回答说，"那好像是他的妻子，我已经把她一起干掉了！"


# 闹钟

作者：朱红锋

我上床的时候是晚上 11 点，窗户外面下着小雪。我缩到被子里面，拿起闹钟，发现闹钟停了--我忘买电池了。天这么冷，我不愿意再起来。我就给妈妈打了个长途电话：

"妈，我闹钟没电池了，明天还要去公司开会，要赶早，你六点的时候给我个电话叫我起床吧。"妈妈在那头的声音有点哑，可能已经睡了，她说："好，乖。"

电话响的时候我在做一个美梦，外面的天黑黑的。妈妈在那边说："小桔你快起床，今天要开会的。"我抬手看表，才五点四十。我不耐烦地叫起来，"我不是叫你六点吗？我还想多睡一会儿呢，被你搅了！"妈妈在那头突然不说话了，我挂了电话。

起来梳洗好，出门。天气真冷啊，漫天的雪，天地间茫茫一片。公车站台上我不停地跺着脚。周围黑漆漆的，我旁边却站着两个白发苍苍的老人。我听着老先生对老太太说："你看你一晚都没有睡好，早几个小时就开始催我了，现在等这么久。"

是啊，第一趟班车还要五分钟才来呢。终于车来了，我上车。车的是一位很年轻的小伙子，他等我上车之后就轰轰地把车开走了。我说："喂，司机，下面还有两位老人呢，天气这么冷，人家等了很久，你怎么不等他们上车就开车？"

那个小伙子很神气地说："没关系的，那是我爸爸妈妈！今天是我第一天开公交，他们来看我的！"

我突然就哭了。我看到爸爸发来的短消息："女儿，妈妈说，是她不好，她一直没有睡好，很早就醒了，担心你会迟到。"

忽然想起一句犹太人谚语：

父亲给儿子东西的时候，儿子笑了。


# 虐猫

作者：汪曾祺

李小斌、顾小勤、张小涌、徐小进都住在九号楼七门。他们从小一块长大，在一个幼儿园，又读一个小学，都是三年级。李小斌的爸爸是走资派。顾小勤、张小涌、徐小进家里大人都是造反派。顾小勤、张小涌、徐小进不管这些，还是跟李小斌一块玩。

没有人管他们了，他们就瞎玩。捞蛤蟆骨朵，粘知了。砸学校的窗户玻璃，用弹弓打老师的后脑勺。看大辩论，看武斗，看斗走资派，看走资派戴高帽子游街。李小斌的爸爸游街，他们也跟着看了好长一段路。

后来，他们玩猫。他们玩过很多猫：黑猫、白猫、狸猫、狮子玳瑁猫（身上有黄白黑三种颜色）、乌云盖雪（黑背白肚）、铁棒打三桃（白身子，黑尾巴，脑袋顶上有三块黑）……李小斌的姥姥从前爱养猫。这些猫的名堂是姥姥告诉他的。

他们捉住一只猫，玩死了拉倒。

李小斌起初不同意他们把猫弄死。他说：一只猫，七条命，姥姥告诉他的。

“去你一边去！什么‘一只猫七条命’！一个人才一条命！”

后来李小斌也不反对了，跟他们一块到处逮猫，一块玩。

他们把猫的胡子剪了。猫就不停地打喷嚏。

他们给猫尾巴上拴一挂鞭炮，点着了。猫就没命地乱跑。

他们想出了一种很新鲜的玩法：找了四个药瓶子的盖，用乳胶把猫爪子粘在瓶盖子里。猫一走，一滑；一走，一滑。猫难受，他们高兴极了。

后来，他们想出了一种很简单的玩法：把猫从六楼的阳台上扔下来。猫在空中惨叫。他们拍手，大笑。猫摔到地下，死了。

他们又抓住一只大花猫，用绳子拴着往家里拖。他们又要从六楼扔猫了。

出了什么事？九楼七门前面围了一圈人：李小斌的爸爸从六楼上跳下来了。

来了一辆救护车，把李小斌的爸爸拉走了。

李小斌、顾小勤、张小涌、徐小进没有把大花猫从六楼上往下扔，他们把猫放了。


# 做起来

作者：伊塔洛 · 卡尔维诺

有这样一个镇子，做什么事情都被禁止了。

现在，因为惟一未被禁止的就是尖脚猫游戏，所以镇上的臣民就经常聚在镇后边的草坪上，成天地玩尖脚猫游戏。

因为禁令被制订的时候总有恰当的原因，所以没有任何人觉得有理由抱怨，也没人觉得受不了。

几年过去了。有一天，官员们觉得再没有任何理由禁止臣民做这些事了，他们就派了传令官四处通知人们一切都开禁了。

传令官来到老百姓喜欢聚集的那些地方。

“听好了，听好了，”他们宣布，“所有的都开禁了。”但人们还是玩尖脚猫游戏。

“明白吗？”传令官重申，“你们现在可以任意做想做的事了。”

“好的，”臣民们回答。“我们玩尖脚猫。”

那些传令官一再地提醒他们的臣民，他们又可以回到他们从前曾经从事的那些高尚而有用的职业中去了。但是老百姓都不愿听，他们继续玩尖脚猫，一圈又一圈，甚至都不停下来喘口气。

看到他们是白费劲，那些传令官就回去禀报上面。

“这很容易，”那些官员们说，“现在我们下令禁止尖脚猫。”

人民就是在那时开始反抗的，杀了部分官员。


# 陈小手

作者：汪曾祺

我们那地方，过去极少有产科医生。一般人家生孩子，都是请老娘。什么人家请哪位老娘，差不多都是固定的。一家宅门的大少奶奶、二少奶奶、三少奶奶，生的少爷、小姐，差不多都是一个老娘接生的。老娘要穿房入户，生人怎么行？老娘也熟知各家的情况，哪个年长的女佣人可以当她的助手，当“抱腰的”，不须临时现找。而且，一般人家都迷信哪个老娘“吉祥”，接生顺当。——老娘家供着送子娘娘，天天烧香。谁家会请一个男性的医生来接生呢？——我们那里学医的都是男人，只有李花脸的女儿传其父业，成了全城仅有的一位女医人。她也不会接生，只会看内科，是个老姑娘。男人学医，谁会去学产科呢？都觉得这是一桩丢人没出息的事，不屑为之。但也不是绝对没有。陈小手就是一位出名的男性的妇科医生。

陈小手的得名是因为他的手特别小，比女人的手还小，比一般女人的手还更柔软细嫩。他专能治难产，横生、倒生，都能接下来 (他当然也要借助于药物和器械)。据说因为他的手小，动作细腻，可以减少产妇很多痛苦。大户人家，非到万不得已则不会请他的。中小户人家，忌讳较少，遇到产妇胎位不正，老娘束手，老娘就会建议：“去请陈小手吧。”

陈小手当然是有个大名的，但是都叫他陈小手。接生，耽误不得，这是两条人命的事。陈小手喂着一匹马。这匹马浑身雪白，无一根杂毛，是一匹走马。据懂马的行家说，这马走的脚步是“野鸡柳子”，又快又细又匀。我们那里是水乡，很少人家养马。每逢有军队的骑兵过境，大家就争着跑到运河堤上去看“马队”，觉得非常好看。陈小手常常骑着白马赶着到各处去接生，大家就把白马和他的名字联系起来，称之为“白马陈小手”。

同行的医生，看内科的、外科的，都看不起陈小手，认为他不是医生，只是一个男性的老娘。陈小手不在乎这些，只要有人来请，立刻跨上他的白走马，飞奔而去。正在呻吟惨叫的产妇听到他的马脖子上的銮铃的声音，立刻就安定了一些。他下了马，即刻进了产房。过了一会儿 (有时时间颇长)，听到哇的一声，孩子落地了。陈小手满头大汗，走了出来，对这家的男主人拱拱手：“恭喜恭喜！母子平安!”男主人满面笑容，把封在红纸里的酬金递过去。陈小手接过来，看也不看，装进口袋里，洗洗手，喝一杯热茶，道一声“得罪”，出来上马，只听见他的马的銮铃声“哗棱哗棱”……走远了。

陈小手活人多矣。

有一年，来了联军。我们那里那几年打来打去的，是两支军队。一支是国民革命军，当地称之为“党军”；相对的一支是孙传芳的军队。孙传芳自称“五省联军总司令”，他的部队就被称为“联军”。联军驻扎在天王庙，有一团人。团长的太太 (谁知道是正太太还是姨太太) 要生了，生不下来。叫来几个老娘，还是弄不出来。这太太杀猪也似的乱叫。团长派人去叫陈小手。

陈小手进了天王庙。团长正在产房外面不停地“走柳”，见了陈小手，说：

“大人，孩子，都得给我保住，保不住要你的脑袋！进去吧!”

这女人身上的脂油太多了，陈小手费了九牛二虎之力，总算把孩子掏出来了。和这个胖女人较了半天劲，累得他筋疲力尽。他移里歪斜走出来，对团长拱拱手：

“团长！恭喜您，是个男伢子，少爷!”

团长呲牙笑了一下，说：“难为你了!——请!”

外边已经摆好了一桌酒席。副官陪着。陈小手喝了两口。团长拿出 20 块大洋，往陈小手面前一送：

“这是给你的!——别嫌少哇!”

“太重了！太重了!”

喝了酒，揣上 20 块现大洋，陈小手告辞了：“得罪!”

“不送你了!”

陈小手出了天王庙，跨上马。团长掏出手枪来，从后面，一枪就把他打下来了。团长说：“我的女人，怎么能让他摸来摸去！她身上，除了我，任何男人都不许碰！你小子太欺负人了！日他奶奶!”团长觉得怪委屈。


# 道德极限

作者：刘瑜

晚上，就一个问题我和蚊米发生了重大争论。

事情是这样的，我问他：如果你几乎不会游泳，但是发现我掉到水库里了，你会跳下去救我吗？

蚊米说：那当然了。

可是你几乎必死无疑啊！没法救活我，自己还白白送上一条命，多不值啊！

可是生死这个东西，没必要看的那么重……我不禁陷入了深思。确切地说，是陷入了焦虑。如果换了我，我会不会去救他呢？更糟的是，如果把那个“他”换成“我妈”、“我爸”、“我儿子”呢？

这样想着时，我脑子里清晰地浮现出一个画面：我的一个亲人消失在漫漫的水面之下，我抖抖瑟瑟地站在岸边不知所措。与此同时，我不可避免地想起电影里，一个母亲看到自己的孩子面临威胁时，奋不顾身地冲进刀山火海的架势。

我更加焦虑了。如此焦虑，似乎这事已经发生过了。

事实上，这个场景是我经常假想的类似的“道德极限”场景之一而已。除了“水库救人”命题，我还分别思考过以下命题：如果一个疯子拿着刀在街上追砍一个儿童，我会不会冲上去与歹徒搏斗？

如果我的小孩掉进养熊的围栏，一只熊正在向他靠近，我该怎么办？

如果我家突然发生大火，我被成功救出，但是我孩子还被围困在火海当中，我要不要冲回去？

这些道德极限场景都有一个特点，就是在危险面前我的努力几乎于事无补，但问题是：相比于事无补的努力并为此付出生命的代价，我是否能够忍受自己在别人极端的痛苦面前无所作为？

想这些干嘛？蚊米说，这不是自寻烦恼吗？

你不能把自己侥幸没有遇上的事情当作假问题啊，我辩解道，就像你不能把自己没有机会犯的错误当作自己不会犯的错误。

对极端情况的想象是认识世界、认识自己的捷径，而太平年代只是模糊人性，好人显不出好，坏人显不出坏。

有一天晚上我甚至梦见了一个“道德极限”的场景：我梦见我的大学宿舍里有一只煤气罐，不知道为什么，煤气罐突然有一个接口松了，眼看着就要爆炸了，我飞快地往外面跑去，边跑就边想：楼上楼下还有那么多人呢，我应该去通知她们啊！可是来不及了，我得起紧逃生。我多自私啊！我太自私了！

就这样，我被吓醒了，醒了之后为自己没有去救楼上楼下的姐妹们而深深自责，我已经暴露了，一个懦夫已经被自己的梦给暴露了。这事有没有真的发生有什么重要呢？运气并不是美德，这可是我自己说的。

当然我可以安慰自己说：只有当一个人能够面对自己的软弱时，他才能真正学会谦卑与宽容。极度焦虑中，我想到了《追风筝的人》里面的一句话：没有良知的人从不承受痛苦。就是说，如果我为此感到痛苦，那一定是因为我良知未泯。如果我甚至为还没有犯下但可能犯下的罪行而感到痛苦，那我肯定非常有良知。走投无路之下，我就是这样，悄悄把对自己的蔑视，转化成了对自己的赞美。


# 符号控制

作者：贝纳尔 · 韦尔贝

加博瑞。内姆罗德平静地坐在一家诊所的候诊室里，尽管椅子并不怎么舒服。突然间，他发现对面墙上的一幅画正沿着墙面移动，接着，整面墙壁开始颤动、扭曲，直至完全消失。他周围的东西没什么看起来像是假的，但是，在原来墙壁的位置上只出现了一个厚厚的“墙”字，还带着括号注解：（厚度，50 公分，内侧粉刷，外侧涂满水泥，用于抵御恶劣气候。）

这么一大串字母在空气中飘浮着。

加博瑞花了好几秒钟才定过神来，看清楚眼前的一切，而且还看到了以前被墙挡住的景象：马路和行人。他走上前去，试着伸出手穿过去，当他把手缩回来的时候，一切又都模糊起来，那堵墙又回到了原来的位置，就是一堵普通的墙，普通得不能再普通的墙。

加博瑞无奈地耸了耸肩，自言自语道：“幻觉，都是幻觉搞的鬼。”毕竟，他来诊所是为了治一直折磨他的偏头疼。他伸了伸懒腰，决定到街上去走走。

这些被它们名字取代的东西……还是挺奇怪的……

加博瑞。内姆罗德在一所中学教哲学，他记得好像上过一节关于词音和词义的课，他当时不是跟学生说如果一个东西没有被命名的话就不存在吗。他揉着太阳穴有些郁闷地想道：“也许大脑都快被这些哲学领域的问题给占据了。”昨天晚上，他还读了一篇《圣经》：上帝给了亚当命名所有动物、事物的权力……那么在这之前，一切都不存在吗？

卡博瑞很快把这个小插曲忘了，接下来的日子里也没有什么特别的事情发生。

但是一个月后，当他注视一只鸽子的时候，他看见的是两个字：鸽子，后面的括号里写着：（327 克，雄性，羽毛灰黑色，叫声“多--降调咪”，左脚微跛，用于装饰花园。）

这次，这些定义一只动物的字句在空中飘浮了二十多秒钟，卡博瑞伸手去摸，“鸽子”就立刻飞了，还拖着后面的括号和长长的一串解释，到了天上很高的地方，它才又重新变成了一只鸟，还跟着几只咕咕叫的母鸽子。

第三次奇遇发生在他家附近的社区游泳池里，就在他不紧不慢畅游的时候，他看到几个大字--“游泳池”，括号里写着：（注满含氯的水，供儿童玩耍以及成人健身。）

这就有点过头了，卡博瑞确信自己已经神经错乱了，他直接就去了一家心理诊所，可是就是在那儿，他却受到了致命的打击。在结束了诊断并拿了抗焦虑症药的处方之后，他在走廊的尽头看见了一面镜子，卡博瑞看见就在他站的地方，只有一个标签，上面写着：人类（高 170 米，65 公斤，气质平庸，面有倦容，戴眼镜，用于检测系统错误。）


# 与人为友

作者：亦舒

有些人生气时．会发誓不再与人类做朋友，情愿接近狗与猫、花与草、山与水。

不知道会不会太偏激。

人与人相处，自古是一项艺术，人之中当然有坏人有奸人、有恶人！也有种特别爱占小便宜的人，又有爱把喜乐建筑在他人不快上的人。

但好人还是不少，不必因噎废食。

太平盛世，自由社会，一个人把另外一个人害得冢散人亡的机会相当之低，小事何用耿耿于怀。

禽兽不如，狠心狗肺之类的控诉亦不宜在日常生活中频频使用。

猫狗固然可爱温驯，且又听从主人命令，但交朋友，还是人类好。

不是没有办法应付的，兵来将当、你虞我诈、虚与蛇委、统统都是良方。

真正吃不消，还可以走为上招，断绝来往。

毋须心灰意冷，与全人类断绝邦交！百步之内．必有芳草。

对他人要求也不宜太高，世人没有完人，谁也不该要求谁忠、孝、义齐备。


# 消失的人

作者：佚名

不知道从什么时候开始，他发现自己的身体逐渐在消失，第一次发现的时候是在早上穿袜子的时候，发现左脚的小脚趾不见了一节，当时以为自己眼花，摸了一下，小脚趾真的短了一截，脚趾怎么会凭空消失了，没有痛楚。他很害怕，上网搜索“脚趾消失了”，却发现没有结果。

从小到大，他最怕医院，一看见医院就想小时候被医生用一个冰冷的铁器，伸到嘴巴里硬生生拔掉牙齿的情节，牙齿与铁器的碰撞产生的声音，常常在他脑海里响起。“他们会把我当怪物吧”。消失了一节小脚趾，让他走路有点不稳，不过自从失业以来，他就很少出门了，吃的、用的在网上购买就会送货上门，于是他开始忘记自己到底多久没出门了。

“大概大家都忘记我了吧”，他是家里的第二个孩子，父母正在老家给大哥带孩子，妹妹也正在为高考努力着，上次回家是过年的时候，原本属于自己的房间变成了大哥孩子的玩具房，于是那个初一的早上，他是在客厅沙发上醒来的。

期间参加了一次高中同学聚会，同学们忘记通知他，幸好路上碰见了，所以就赶上了，聚会里，那个老教师没有叫出他的名字，老同学聊的故事里自己也没有出现，明明一起拍的运动会照片，竟然也因为自己弯身系鞋带而没拍到。他常常觉得自己可以成为一个出色的小偷，因为无论是姓名、样貌还是身形都难以让人印象深刻。而这些条件都是小偷应该有的。

身体逐渐消失的恐惧并没有维持很久，因为他发现消失的部分一点都不痛，也不会难看，就像母亲搓的面粉，切一刀，面粉自然恢复，只是小了。他每天观察身体的变化，从小脚趾逐渐到整个左脚。还好先消失的是脚，手还能打字，也还能签字，所以他网购了一架轮椅。左脚到右脚，然后下半生逐渐也在消失，他开始停掉进食，因为他也没有饥饿的感觉，后来左手到右手，现在他只能躺在床上，透过窗口的光线感知时间的变化。

有一天，他开始哭，泪水仿佛要从消失的身体中释放出来一样，他想起家人想起年轻时暗恋的姑娘，还有自己小时候的梦想，最后，床上只有一个被泪水浸湿的枕头，水份慢慢被蒸发，这个人真的消失了。


# 时间旅行

作者：海茵莱茵

一九四五年的一天，克力富兰的孤儿院里出现了一个神秘的女婴珍尼，没有人知道她的父母是谁。她孤独地长大，没有任何人与她来往。直到一九六三年的一天，她莫明其妙地爱上了一个流浪汉，情况才变得好起来。可是好景不长，不幸事件一个接一个的发生。首先，当她发现自己怀上了流浪汉的小孩时，流浪汉却突然失踪了。其次，她在医院生小孩时，医生发现她是双性人，也就是说她同时具有男女性器官。为了挽救她的生命，医院给她做了变性手术，她变成了他。最不幸的是，她刚刚生下的小女孩又被一个神秘的人给绑走了。这一连串的打击使他从此一蹶不振，最后流落到街头变成了一个无家可归的流浪汉。直到一九七八年的一天，他醉熏熏地走进了一个小酒吧，把他一身不幸的遭遇告诉了一个比他年长的酒吧伙计。酒吧伙计很同情他，主动提出帮他找到那个使‘他’怀孕而又失踪的流浪汉。唯一的条件是他必须参加伙计他们的‘时间旅行特种部队’。他们一起进了‘时间飞车’。飞车回到六三年时，伙计把流浪汉放了出去。流浪汉莫明其妙地爱上了一个孤儿院长大的姑娘，并使她怀了孕。伙计又乘‘时间飞车’前行九个多月，到医院抢走了刚刚出生的小女婴，并用‘时间飞车’把女婴带回到一九四五年，悄悄地把她放在克力富兰的一个孤儿院里。然后再把稀里糊涂的流浪汉向前带到了一九八五年，并且让他加入了他们的‘时间旅行特种部队’。流浪汉有了正式工作以后，生活走上了正轨。并逐渐地在特种部队里混到了相当不错的地位。有一次，为了完成一个特殊任务，上级派他飞回一九七零年，化装成酒吧伙计去拉一个流浪汉加入他们的特种部队……


# 情债肉偿

作者：张小娴

一个女人，在决定离开一个男人之前，再和他睡一次，以补偿他对她多年来的爱。

她爱上了另一个男人，在两者之间，选择了后来者，因为内疚，她对旧情人说：“今天晚上我和你睡，但明天醒来，我就要离开你。”

她躺在床上，不断回忆旧情，使她可以接受这一刻伏在她身上的男人，她现在不爱他，但她从前是爱他的，她知道现在他仍爱她，所以给它最后的快乐。

我不明白什么男人可接受这种补偿，这根本是一种施舍。

女人说：“我不爱你，但你来吧。”

这不是施舍又是什么？

只有女人才会那么天真，情偿肉债。

男人如果爱这个女人，如果尊重她，也尊重自己就应该一口拒绝这种施舍。

没有爱的性，只是交易或发泄，以此作为一段情的休止符，实在毫无格调，也毫不高尚。

有尊严的男人应该拒绝施舍，告诉她：“你以为男人这么容易就可以来的吗？”

接受了这种施舍，这个男人在这个女人心中就会失去地位，因为她已经还了债，永不会内疚。

惟有拒绝，才会得到女人的尊重。

如果爱一个女人，男人也应该拒绝，使她知道不要用自己的肉体补偿些什么，一个肯接受补偿的男人，对这个女人的爱，太浅太薄了。


# 铁血恋爱

作者：蔡康永

亲爱的宝宝：

我小时候被很多残酷又迷人的爱情故事暗暗地吓过好几跳，虽然那时还没恋爱，但已经觉得这玩意似乎是未来人生的重要戏码，来势汹汹，才会到处埋伏下这么多郑重宣告“即将上映、不容错过”的预告片。

这些爱情故事里，有一个古中国的，非常冷酷。

故事是说一个君王，带着军队，出发去打仗，沿路停停走走，直到一处水边扎营时，君王和长驻水边的女神恋爱了。

他们缠绵了一段时间，直到君王惊觉他再不离开，继续踏上征途的话，他的军队将要瓦解，他该打的那场仗会毫不留情地抛弃他，片面宣布他可笑的缺席，和他缺席必然带来的，他的战败。

君王坚持向女神道别，女神挽留他，怎么留也留不住。女神只好答应放他走。

第二天早上，君王整顿好军队，准备要出发，走出居住的洞口一看，天却是黑的，原来满天飞舞着飞虫，密密麻麻，完全遮蔽了天空。要上路的君王，不要说是前进，连辨认阳光的方向都不能。

君王无奈地退回洞里，女神又出现，安慰他，叫他耐心多呆一天，和他缠绵。

又过了一天，君王走出洞外，又是满天飞虫，遮蔽天空和道路。君王只好再退回洞里。

这样过了三天，君王在第三天的夜晚告诉女神，说他出征后，将会再回到这水边来找他相聚。君王郑重地为女神围上一条珍贵的绿色腰带，说这腰带就是两人爱情的证物，要她好好珍藏。

女神围上腰带，虽然感动，但也知道君王心意已决，下次日出时他一定会全力突破困难离去。

次日一早，果然君王早已披挂好武器，准备无论如何要走了。没想到飞虫竟然变成了两三倍之多，简直把白天变成了黑夜。

君王瞇起眼睛，搜寻着飞虫，终于发现最上空有一只飞虫，腰上有一道鲜明的绿色，君王拉开弓箭，“嗖”的一箭，射穿了那只绿腰的飞虫，绿腰飞虫坠落，在半空就已还原成了绑着绿腰带的女神，轻轻掉落在水里，死了。

女神一死，满天她幻化出来的飞虫瞬间消失不见，晴空万里，君王带队离去。

宝宝啊，故事讲完了。

如何？


# 太阳黑子

作者：亦舒

我不喜欢延迟欢乐，故新衣要即刻穿，礼物要马上拆，脾气也得即时发作。

口头禅是“太阳黑子随时会爆炸”，这是真的，太阳其实是一只大火球，不住燃烧，那狂热火焰时常跳跃，血红色球体上有无数黑点，爆炸起来，威力等于数兆亿个氢弹，足以毁灭整个太阳系。

即使太阳无事，人类本身掌握的核武器，也足以摧毁十个地球。

还不及时行乐，简直同自己过不去，干嘛要那么笨！

想要见谁立刻约他出来嘛，要干杯马上干掉，人无百岁寿，直接点爽快点，切莫扭扭捏捏。

趁现在心情好，马上把想做的事情做掉，免得明日有突然事件令心情欠佳什么都不想做。

生命无常，一深思只觉凄茫，只得苦中作乐，消极抵抗，绝对不等明天，今天就是今天。

一收到新书立刻迷头迷脑地看，明天太阳黑子可能爆炸，地震、海啸，哪一国不知同哪一国也许就干了起来殃及无辜。

不要叫我等。


# 蚂蚁人生

作者：维尔伦

鳏夫布奇今年 90 岁了，而且看样子，他至少还有 20 个年头好活。

布奇从来不谈论自己的长寿之道，他平时就是个寡言少语的人。

布奇虽然不爱说话，却很乐于帮助别人。这一点使他赢得了不少莫逆之交。据他的朋友说，他母亲生他时难产死了。5 岁那年，他家乡闹水灾，大水一直漫到天边。他坐在一块木板上，他的父亲和几个哥哥扶着木板在水里游着。他眼看着一个个浪头卷走他的生命之舟旁的几个哥哥，当他看到陆地的时候，父亲的力气也用完了。他是全家唯一的幸存者。他活泼的眼神从此变得呆滞了，他的眼前似乎总是弥漫着一片茫茫的大水。

布奇结了婚，美丽的妻子为他生了五个可爱的孩子。三个男孩，两个女孩。他渐渐忘记了过去的痛苦，成了世界上最幸福的人。他们全家出去郊游，布奇雇了一辆汽车，可是汽车不够宽敞，他只好骑着自行车兴致勃勃地跟在后面。这时车祸发生了。那一瞬间，他的眼神又变得像木头一样呆滞。布奇又成了孤身一人。

此后，鳏夫布奇再也没结过婚。他当过兵，出过海，他没日没夜地跟苦难的朋友待在一起，倾尽全力帮别人忙，也经历了数不清的大风大浪。然而，死神逼近的时候，老像没看见他似的，总是拥抱别的灵魂。

90 岁的布奇不知什么时候站在我们身后，他苍凉的声音像远古时期的洪流冲击着每一个人：

“一窝蚂蚁抱成足球那么大的一团，漂浮在离我 10 米远近的水面上。每一秒都有蚂蚁被洪水冲出这个球。当这窝蚂蚁跟 5 岁的我一起登上陆地时，它们竟还有网球那般大小。”


# 风骚和魅力

作者：周国平

风骚，放荡，性感，这些近义词之间有着细微的差别。

"性感"译自西文 sexappeal，一位朋友说，应该译作汉语中的"骚"，其含义正相同。怕未必，只要想想有的女人虽骚却并不性感，就可明白。

"性感"是对一个女人的性魅力的肯定评价，"风骚"则用来描述一个女人在性引诱方面的主动态度。风骚也不无魅力。喜同男性交往的女子，或是风骚的，或是智慧的。你知道什么是尤物吗？就是那种既风骚又智慧的女子。

放荡和贞洁各有各的魅力，但更有魅力的是二者的混合：荡妇的贞洁，或贞女的放荡。

调情之妙，在于情似有似无，若真若假，在有无真假之间。太有太真，认真地爱了起来，或全无全假，一点儿不动情，都不会有调情的兴致。调情是双方认可的意淫，以戏谑的方式表白了也宣泄了对于对方的爱慕或情欲。

昆德拉的定义是颇为准确的：调情是并不兑现的性交许诺。

一个真正有魅力的女人，她的魅力不但能征服男人，而且也能征服女人。因为她身上既有性的魅力，又有人的魅力。

好的女人是性的魅力与人的魅力的统一。好的爱情是性的吸引与人的吸引的统一。好的婚姻是性的和谐与人的和谐的统一。

性的诱惑足以使人颠倒一时，人的魅力方能使人长久倾心。

大艺术家兼有包容性和驾驭力，他既能包容广阔的题材和多样的风格，又能驾驭自己的巨大才能。

好女人也如此。她一方面能包容人生丰富的际遇和体验，其中包括男人们的爱和友谊，另一方面又能驾驭自己的感情，不流于轻浮，不会在情欲的汪洋上覆舟。


# 我只要一种

作者：朵拉

突然走进一个多选择时代。

从前是一个人衣橱里有三件衣服已经太多，换来换去，白衣配黑裙，不然就黑裙配白衣。脚上的鞋子是一双三用，走路跑步吃宴会。假如有个人拥有四件衣服两双鞋子，嘿，那不得了，他肯定是来自富裕之家。

当年在物质上大家都是穷的，要买个家用品或者是电器等等什么的，只设定一个目标，就那几个著名牌子之中选一个。

突然，一切就变了样。超市、商场、购物中心、大卖场，到处都是，逛了一家换一家，要买样东西，想找样小用品，也有太多的名牌，太多的选择，满山满谷那样的快溢出来的样子，走到头昏脑涨，看到眼花缭乱，你还是无法作出最佳的选择。

一切都太多太多了。结果是怎么样？太多选择没目标，最后索性通通都不要。

比如去最爱的乳酪蛋糕店，坐下，对着印刷精美的菜单，挑选心目中最理想口味的乳酪蛋糕。

咖啡、香蕉巧克力、红莓、提拉米苏、纯乳酪……天呀，怎么没有不爱的？

原来我们不是进来选自己最喜欢的，而是进来学习如何放弃。选 A，不舍得 B ;选 B，会想念 c ;选 C，那么就一直幻想 D 的味道；选 D 呢，难道不要 E 了？不不不，最后混淆不清，到底哪一种最合口味？

爱死了乳酪蛋糕，真正走进蛋糕店，心里交战半天，最后只唤杯咖啡。

不想被选择破坏好心情。可以有哪个地方，不要有那么多选择的吗？


# 不朽的失眠

作者：张晓风

他落榜了！1200 年前。榜纸那么大那么长，然而，就是没有他的名字，单单容不下他的名字“张继”两个字。

考中的人，姓名一笔一划写在榜单上，天下皆知。奇怪的是，在他的感觉里，考不上才是天下皆知。这件事，令他羞愧沮丧。

离开京城吧！议好了价，他踏上小舟。本来预期的情节不是这样的，本来也许有插花游街、马蹄轻疾的风流，有衣锦还乡袍笏加身的荣耀。然而，寒窗十年，虽有他的悬梁刺股，琼林宴上，却并没有他的一角席次。

船行似风。

江枫如火，在岸上举着冷冷的爝焰。这天黄昏，船，来到了苏州，但这美丽的古城，对张继而言，也无非是另一个触动愁情的地方。

如果说白天有什么该做的事，对一个读书人而言，就是读书吧！夜晚呢？夜晚该睡觉以便养足精神第二天再读。然而，今夜是一个忧伤的夜晚。今夜，在异乡，在江畔，在秋冷雁高的季节，允许一个落魄士子放肆的忧伤。江水，可以无限度地收纳古往今来一切不顺遂之人的泪水。

这样的夜晚，残酷地坐着，亲自听自己的心正被什么东西啮噬而一分一分消失的声音，而且眼睁睁地看着自己的生命如劲风中的残灯，所有的力气都花在抗拒上了，油快尽了，微火每一刹那都可能熄灭。然而，可恨的是，终其一生，它都不曾华美灿烂过啊！

江山睡了，船睡了，船家睡了，岸上的人也睡了。惟有他，张继，醒着，夜愈深，愈清醒，清醒如败叶余落的枯树，似梁燕飞去的空巢。

起先，是睡眠排拒了他。（也罢，这半生，不是处处都遭排拒吗？）尔后，是他在赌气，好，无眠就无眠，长夜独醒，就干脆彻底来为自己验伤，有何不可？

月亮西斜了，一副意兴阑珊的样子。有鸟啼，粗嘎嘶哑，是乌鸦，那月亮被它一声声叫得更黯淡了。江岸上，想已霜结了千草。夜空里，星子亦如清霜，一粒粒零落凄绝。

在须角，在眉梢，他感觉，似乎也森然生凉，那阴阴不怀好意的凉气啊，正等待凝成早秋的霜花，来贴缀他惨淡少年的容颜。

江上渔火三二，他们在干什么？在捕鱼吧？或者，虾？他们也会有撒空网的时候吗？世路艰辛啊！即使潇洒的捕鱼人，也不免投身在风波里吧！

然而，能辛苦工作，也是一种幸福吧！今夜，月自光其光，霜自冷其冷，安心的人在安眠，工作的人去工作。只有我张继，是天不管地不收的一个，是既没有权利去工作，也没有福气去睡眠的一个……

钟声响了，这奇怪的深夜的寒山寺钟声。一般寺庙，都是暮鼓晨钟，寒山寺庙敲“夜半钟”，用以警世。钟声贴着水面传来，在别人，那声音只是睡梦中模糊的衬底音乐。在他，却一记一记都撞击在心坎上，正中要害。钟声那么美丽，但钟自己到底是痛还是不痛呢？

既然无眠，他推枕而起，摸黑写下“枫桥夜泊”四字。然后，就把其余 28 个字照抄下来。我说“照抄”，是因为那 28 个字在他心底已像白墙上的黑字一样分明凸显：

月落乌啼霜满天，

江枫渔火对愁眠。

肆苏城外寒山寺，

夜半钟声到客船。

感谢上苍，如果没有落第的张继，诗的历史上便少了一首好诗，我们的某一种心情，就没有人来为我们一语道破。

1200 年过去了，那张长长的榜单上（就是张继挤不进的那张金榜）曾经出现过的状元是谁？哈！管他是谁，真正被记得的名字是“落第者张继”。有人会记得那一届状元披红游街的盛景吗？不！我们只记得秋夜的客船上那个失意的人，以及他那场不朽的失眠。


# 秋天的怀念

作者：史铁生

双腿瘫痪后，我的脾气变的暴怒无常。望着望着天上北归的雁阵，我会突然把面前的玻璃砸碎；听着听着李谷一甜美的歌声，我会猛地把手边的东西摔向四周的墙壁。这时，母亲就悄悄地躲出去，在我看不见的地方偷偷地听着我是动静。当一切恢复沉寂，她又悄悄地进来，眼边红红的，看着我。“听说北海的花儿都开了，我推着你去走走。”她总是这么说。母亲喜欢花，可自从我的腿瘫痪后，她侍弄的那些花都死了。“不，我不去！”我狠命的捶打这两条可恨的腿，喊着：“我可活什么劲！”母亲扑过来抓住我的手，忍住哭声说：“咱娘俩在一块，好好儿活，好好儿活……”

可我却一直都不知道，她的病已经到了那步田地。后来妹妹告诉我，她经常肝疼得整宿翻来覆去的睡不了觉。

那天我又独自坐在屋里，看着窗外的树叶“刷刷啦啦”的飘落。母亲进来了，挡在窗前：“北海的菊花开了，我推你去看看吧。”她憔悴的脸上显出央求般的神色。“什么时候？”“你要是愿意，就明天？”她说。我的回答已经让她喜出望外了，。“好吧，就明天。”我说。她高兴的一会儿坐下，一会站起来：“那就赶紧准备准备。”“唉呀，烦不烦？几步路，有什么好准备的！”她也笑了，坐在我的身边，絮絮叨叨地说着：“看完菊花，咱们去‘仿膳’，你小时候最爱吃那儿的豌豆黄儿。还记得那回我带你去北海吗？你偏说那杨树花是毛毛虫，跑着，一脚踩扁一个……”她忽然不说了。对于“跑”和“踩”一类的字眼她比我还敏感。她又悄悄地出去了。

她出去了，就再也没回来。

邻居把她抬上车时，她还在大口大口地吐着鲜血。我没想到她已经病成那样。看着三轮车远去，也决没有想到那竟是永远的诀别。

邻居的小伙子背着我去看她的时候，她正艰难地呼吸着，像她艰难的一生。别人告诉我，她昏迷前的最后一句话是：“我那个有病的儿子和我那个还未成年的女儿……”

又是秋天，妹妹推着我去北海看了菊花。黄色的花淡雅，白色的花高洁，紫红色的花热烈而深沉，活泼洒洒，秋风中正开得烂漫。我懂得母亲没有说完的话，妹妹也懂。我俩在一块儿，好好儿活……


# 午夜的汽笛

作者：村上春树

女孩问男孩：“你喜欢我喜欢到什么程度？”

少年想了想，用沉静的声音说：“半夜汽笛那个程度。”

少女默默地等待下文---里面肯定有什么故事。

“一次，半夜突然醒来。”他开始讲述，“确切时间不清楚，大约两三点吧，也就那个时间。什么时候并不重要，总之是夜深时分，我完完全全孤单一人，身边谁也没有。好吗，请你想象一下：四下漆黑一片，什么也看不见，什么也听不见，就连时钟声都听不见，也可能钟停了。我忽然觉得自己正被隔离开来，远离自己认识的人，远离自己熟悉的场所，远得无法置信。在这广大世界上不为任何人爱，不为任何人理解，不为任何人记起---我发现自己成了这样的存在。即使我就这么消失不见，也没有人察觉。那种心情，简直就像被塞进厚铁箱沉入深海底。由于气压的关系，心脏开始痛，痛得像要咔哧咔哧裂成两半。这滋味你可知道？”

少女点点头。想必她是知道的。

少年继续说道：“这大概是人活着的过程中所能体验到的最难以忍受的一种感觉。又伤心又难受，恨不得直接死掉算了。不不，不是这样，不是死掉算了，而是假如放在那里不管，就真的死掉了，因为铁箱里的空气越来越稀薄了。这可不是什么比喻，是真的。这也就是深夜里孤单单醒来的含义。这你也明白？”

少女再次默默点头。少年停了一会儿。

“不过当时听见很远很远的地方有汽笛声，非常非常遥远。到底什么地方有铁路呢？莫名其妙。总之就那么远。声音若有若无，但我知道那是火车的汽笛声，肯定是。黑暗中我竖耳细听，于是又一次听到了汽笛声。很快，我的心脏不再痛了，时针开始走动，铁箱朝海面慢慢浮升。而这都是因为那微弱的汽笛声的关系。汽笛声的确微弱，听见没听见都分不清，而我就像爱那汽笛一样爱你。”


# 多美的故事

作者：奥斯卡 · 王尔德

一个英俊的少年，天天到湖边去欣赏自己的美貌。他对自己的容貌如痴如醉，竟至有一天掉进湖里，溺水身亡。他落水的地方，长出一株鲜花，人们称之为水仙。

水仙少年死后，山神女神来到湖边，看见一湖淡水变成了一潭咸咸的泪水。

“你为何流泪？”山林女神问道。

“我为水仙少年流泪。”湖泊回答。

“你为水仙少年流泪，我们一点也不惊讶。”山林女神说道，“我们总是跟在他后面，在林中奔跑，但是，只有你有机会如此真切地看到他英俊的面庞。”

“水仙少年长得漂亮吗？”湖泊问道。

“还有谁比你更清楚这一点呢？”山林女神惊讶地回答，“他每天都在你身边啊。”

湖泊沉默了一会儿，最后开口说：“我是为水仙少年流泪，可我从来没有注意他的容貌。我为他流泪，是因为每次他面对我的时候，我都能从他眼睛深处看到我自己的美丽映像。


# 相信不相信

作者：龙应台

二十岁之前相信的很多东西，后来一件一件变成不相信。

曾经相信过文明的力量，后来知道，原来人的愚昧和野蛮不因文明的进展而消失，只是愚昧野蛮有很多不同的面貌：纯朴的农民工人、深沉的知识份子、自信的政治领袖、替天行道的王师，都可能有不同形式的巨大愚昧和巨大野蛮，而且野蛮和文明之间，竟然只有极其细微、随时可以被抹掉的一线之隔。

曾经相信过正义，后来知道，原来同时完全可以存在两种正义，而且彼此抵触，冰火不容。选择其中之一，正义同时就意味着不正义。而且，你绝对看不出，某些人在某一个特定的时机热烈主张某一个特定的正义，其中隐藏着深不可测的不正义。

曾经相信过理想主义者，后来知道，理想主义者往往经不起权力的测试：一掌有权力，他或者变成当初自己誓死反对的“邪恶”，或者，他在现实的场域里不堪一击，一下就被弄权者拉下马来，完全没有机会去实现他的理想。理想主义者要有品格，才能不被权力腐化；理想主义者要有能力，才能将理想转化为实践。

曾经相信过爱情，后来知道，原来爱情必须转化为亲情才可能持久，但是转化为亲情的爱情，犹如化入杯水中的冰块—它还是冰块吗？

曾经相信过海枯石烂作为永恒不灭的表征，后来知道，原来海其实很容易枯，石，原来很容易烂。雨水，很可能不再来，沧海，不会再成桑田。原来，自己脚下所踩的地球，很容易被毁灭。

二十岁之前相信的很多东西，有些其实到今天也还相信。

譬如国也许不可爱，但是土地和人可以爱。譬如史也许不能信，但是对于真相的追求可以无止尽。譬如文明也许脆弱不堪，但是除文明外我们其实别无依靠。譬如正义也许极为可疑，但是在乎正义比不在乎要安全。譬如理想主义者也许成就不了大事大业，但是没有他们社会一定不一样。譬如爱情总是幻灭的多，但是萤火虫在夜里发光从来就不是为了保持光。譬如海枯石烂的永恒也许不存在，但是如果一粒沙里有一个无穷的宇宙，一刹那里想必也有一个不变不移的时间。

那么，有没有什么，是我二十岁前不相信的，现在却信了呢？

有的，不过都是些最平凡的老生常谈。曾经不相信“性格决定命运”，现在相信了。曾经不相信“色即是空”，现在相信了。曾经不相信“船到桥头自然直”，现在有点信了。曾经不相信无法实证的事情，现在也还没准备相信，但是，有些无关实证的感觉，我明白了，譬如李叔同圆寂前最后的手书：“君子之交，其淡如水。执象而求，咫尺千里。问余何适，廓尔忘言。华枝春满，天心月圆。”

相信与不相信之间，仿佛还有令人沉吟的深度。

我们总是在相信与不相信之间挣扎。


# 清晨的变故

作者：黑井千次

光男早晨醒来，发现枕边有一片白纸。他拿起一看，是折叠着的纸条，上面好像写着什么。他打开窗帘读完了这张纸条，不由得大吃一惊。

光男，我已经无法忍耐这种生活，请让我离开这个家。13 年来，承蒙关照。你也要保重身体，良子。

他只穿上一条裤腿就往外跑，一不小心摔了个跟头。在他急急忙忙要爬起来的时候，听到厨房里响着与每天早晨同样的做饭声。现在良子还在，是不是一会儿就要离家出走？

“早晨好！”

妻子从水池子前回过头来，脸色与昨天一样，没有任何异常。

“这封信是怎么回事？”

“你看了？就是那么回事。”

“别开玩笑。吓了我一跳。”

“我不是开玩笑，是很认真的。”

“可是，良子不是在这里吗？”

“不，大清早就走了。”

“……那么，你是谁？”

“你还没睡醒吧？我是你的妻子呀！”

“良子就是我的妻子。”

“什么，你果真这样想？”

“当然。我和良子结的婚……”

“天亮时，良子就提着白色旅行包走了。这里剩下的只有你的妻子。”

听妻子这样充满自信地说，他糊涂了。

“那么我问你，我到底是谁？”

“傻瓜！你不是我的丈夫吗？”

“那么，光男这个人跑到哪里去了？”

“怎么，你不知道？他不是光着脚追良子去了吗？他边跑边喊，我不好！我不好！”

光男一下子没了主心骨，依稀觉得好像确实有这么一回事。

上班的时间到了，光男精神恍惚地走出了家门。

“您走好！”

妻子清脆地说。

到了公司，他忍不住把今天早晨家里发生的事与一个最信赖的同事说了。

“怎么，你家还是这个样子？”那个同事满不在乎地说，“我家五年前就发生过这样的事了。幸好现在夫妻关系还算圆满。”

“那么，出走的那两个人怎么样了？”

“嗯……是不是倒在什么地方死了？”


# 真实的高贵

作者：海明威

风平浪静的大海，每个人都是领航员。

但是，只有阳光而无阴影，只有欢乐而无痛苦，那就不是人生。以最幸福的人的生活为例——它是一团纠缠在一起的麻线。丧母之痛和幸福祝愿彼此相接，是我们一会伤心，一会高兴，甚至死亡本身也会使生命更加可亲。在人生的清醒的时刻，在哀痛和伤心的阴影之下，人们真实的自我最接近。

在人生或者职业的各种事务中，性格的作用比智力大得多，头脑的作用不如心情，天资不如由判断力所节制着的自制，耐心和规律。

我始终相信，开始在内心生活得更严肃的人，也会在外表上开始生活得更朴素。在一个奢华浪费的年代，我希望能向世界表明，人类真正需要的的东西是非常之微少的。

悔恨自己的错误，而且力求不再重蹈覆辙，这才是真正的悔悟。优于别人，并不高贵，真正的高贵应该是优于过去的自己。


# 神秘领奖人

作者：劳瑞斯

迈克买彩票中了 1000 万美元。领奖那天，他穿上黑色长袍，戴上黑色面罩，把头和脸都襄得严严实实，只露出眼睛、鼻子和嘴巴。

迈克仍然感觉不太保险。他又用墨水把眼圈描黑，在鼻子上贴了一块胶布，给嘴巴化了个花妆，使嘴巴看起来像被烧焦了一样，惨不忍睹。

迈克顺利领到奖金。第二天，他领奖金时的模样被登到报纸上，身边的人都没认出来。

过了 3 个月，迈克一看还没有人怀疑他，就打算放心挥霍奖金了。他从纽约飞到旧金山度假。

一天晚上，迈克来到一家酒吧，喝了些酒，很兴奋。他看到不远处坐着个愁眉苦脸的男人，便喊道：“嘿，伙计，过来坐吧，我请你喝一杯。”

男人来到他的桌子前坐下，迈克豪爽地叫了一瓶昂责的酒。男人激动得连喝三杯，恭维说：“谢谢您，先生，我从来没有见过像您这样豪爽的有钱人。如果这是在纽约，我会认为您就是那个神秘的中奖人。”

迈克发出一阵得意的大笑，兴致勃勃地和他聊起来：“我就是从纽约来的。”

男人说：“我在纽约一直过得很好，直到发生一件事，改变了我的人生”

迈克饶有兴趣地问：“哦，能否说给我听听？”

男人苦笑道：“我在纽约认识两个女人，和她们同时保持来往。一天夜里，当我在一个女人家里睡觉时，她丈夫突然回来……”

“哦”迈克露出会心的微笑。

男人接着说：“女人的丈夫是个拳击教练。他把我从床上像抓小鸡一样拎起来，连打两拳，然后从窗口扔了出去。”

迈克同情地叹着气：“是吗？真倒霉。”

男人懊恼地说：“还有更倒霉的事呢．当我爬起来逃跑时，一不小心撞到电线杆上，痛得几乎要死过去。”

迈克发出同情的笑声：“呵呵，太倒霉了。”

男人摇摇头说：“这还没完呢。我光着身子跑到第二个女人家。她当时正在给我熨西服，看见我的模样，还没等我解释，就拿着熨斗向我砸来……”

迈克忍不住大笑起来：“朋友，倒霉的一天。，”

男人痛苦地说：“不，倒霉的并不只这一天。您不知道第二天发生了什么。当我带着黑眼圈，鼻子上贴着胶布，抚摸着被熨斗烫伤的嘴巴来到公司时，老板和全体同事立刻把我包围，祝贺我中了 1000 万美元大奖。”

迈克难以置信地瞪大眼睛，捧着肚子笑得钻到桌子底下。

男人可怜巴巴地说：“您笑吧，豪爽的朋友。接下去，正如您猜想的那样，我虽然没有中奖，却麻烦不断，以致再也无法在纽约生活下去了。我真不明白，那个该死的家伙为什么要扮成那副模样去领奖。”


# 幸福的夜晚

作者：黑井千次

深夜，电话铃响了起来。

丈夫起身看了看枕边的表，2 点 30 分。自动显示数字的表盘在黑暗中闪烁着蓝色的幽光。

“这时候怎么还有电话？”

他对坐在身旁被子上的妻子说。

“真是活见鬼。”

妻子不安地回答。

“我去接。”

他说着，急忙拉开了台灯。寝室里立刻充满了柔和的灯光，在妻子对面的被窝里，孩子蜷缩着身体睡得正香。他走进客厅，借着寝室透过来的微光，拿起了话筒。

“喂，你是×××吗？”

还没等他说话，耳机中突然响起一个陌生男人的声音。

“是的。”

他浑身一抖，赶忙答道。

“很好。老实告诉你，我把你的孩子拐出来了，他现在在我这里。”

他大吃一惊，回身望着寝室，并用手捂住话筒，叫他的妻子确认一下孩子是否还在。

“你这是怎么了？孩子不是在这里睡得好好的吗？”

听到妻子的回答，他拿起话筒说：

“喂喂，你是把电话号码搞错了吧？我家的孩子正在家里睡觉。”

“不过，你确实是×××吧？”对方好像有点心虚似地说，“这就对了，没有错。如果你爱你的孩子，那么在三分钟后，就拿着钱到拐角处的电线杆子下面来。”

“我当然爱我的孩子，不过他在家里……”

“少罗唆，听我说。这里并不远，你马上准备五千日元到这里来，怎么，拿不出这点钱吗？”

“五千日元倒没什么……”

还没等他说完，电话就挂上了。

疑惑中，他穿上衣服，从钱包里抽出一张五千日元的钞票握在手里。

妻子说应该叫警察，他没有理睬，只说了一句我马上回来，就打开了大门。

他来到街上，果然看到在拐角处的电线杆子下面，站着一个无精打采的小个子男人。

“这是怎么回事？我的小孩正在家里睡觉呢。”

他说着，小心翼翼地向那个人走去。那个人慢慢地仰起脸说：

“是吗？那很好。是个很幸福的家庭啊！”

“姑且可以……”

“这种幸福用五千日元就能买到，难道还不算便宜吗？”

那个人伸出了手。他把那张五千日元的钞票顺势放在他的手上。这时，他心里想，不管怎么说，五千日元都太少了点。


# 幸福的生日

作者：黑井千次

“看，有人给你送礼物来了。”走出房门来迎接他的妻子，在说“你回来啦”之前，突然对丈夫这么说。弯腰脱鞋的丈夫发现鞋箱上放着一盆花。

“噢，这花很漂亮。好像是洋兰。哪里来的？”

丈夫回答道，心里却突然涌起一种不祥之感。

“不知道。我出去买东西时，花店送来的。我不在，所以寄放在邻居家里了。”

他避开妻子的目光，仔细端详这盆花。细竹支撑着的修长纤弱的茎上开着三朵淡紫色的花。在另一棵茎的顶端，有两个胖乎乎的暗紫色的花蕾。几片干燥厚重的叶子耷拉在盆边上，整棵花赤裸裸地挺立着，上面好像只有花和蕾。

“上面还附着一张卡片。”

妻子说着，拿出一张卡片。上面写着：祝贺你的生日。现在我仍然爱你。

为了不叫妻子发现他脸色的变化，他弯腰面对着鞋。

“这是谁送来的呢？”

“……哎呀，我也想不起来。”

“这就怪了。”

妻子扔下蹲在那里不起来的丈夫，咚咚咚向厨房走去。

这个混蛋！丈夫心里骂道，我的苦衷她一点也不理解。一股怒火在他的心里燃烧。

妻子打开了一瓶莆萄酒，为他祝贺生日。但飞来的那盆花，却使这个夜晚罩上了一层阴影。伺候孩子睡觉后，两个人在起居室里相对而坐，丈夫总是躲开妻子的目光。

“这样干坐着实在无聊。你好好想想，就一点想不起来？”

妻子还是穷追不舍。在妻子没完没了的追问下，他哼哼唧唧地说，也许是过去的女友心血来潮送来的生日礼物吧。

“什么样的女朋友，我怎么没听你说过？”

妻子突然板起脸来。

“你别急，不是你所想象的那种关系。”

“你知道我是怎样想的？”

看见妻子的眼睛里一下子涌满了泪，丈夫狼狈不堪，手足无措。这下子糟了，我不应该瞒着她。都是那花引起的麻烦，我马上把它扔了。当他满腹懊恼地站起来时，泪流满面的妻子轻轻地说：

“我不是开玩笑，你，已经不认识我的字了……”


# 我有事找你

作者：张小娴

好想见他，又找不到什么藉口，于是，只好在电话里认真的跟他说：“我有事找你。”

“好吧。”他说。

太好了！他来到约定的地方。我望着他，等他说话。他好生奇怪，心里在想：“她不是说有事找我的吗？”

他首先打开话匣子，我快乐地跟他聊天，又不停吃东西，胃口好得不得了，就是没说我找他有什么事。

回家的路上，我们聊了很多事情。今天晚上，我过得很开心。分手的时候，我完全忘记了我找他有什么事，他也忘记了问我。

我没有什么特别的事情。我们之间有点云雾，有点暧昧，我很想见你，又怕被你拒绝。事情就是这么简单。

“我有事找你。”这一句话，总是被女人普遍地使用。

很想跟已经分手的男朋友见面，又怕他不肯来，我们只好在电话里煞有介事的说：“我有事找你。”

假如你对我尚有一丝关怀，你就来吧。请你不要冷漠的问我：“你有什么事？”

我不过想见你。


# 我是个窃贼

作者：阿·康帕尼尔

“是的，我是个窃贼。”老头伤心地说，“可我一辈子只偷过一次，那是一次最奇特的扒窃，我偷了一个装满钱的钱包。”

“这没有什么稀奇的。”我打断了他的话。

“请让我说下去。当我把偷到的钱包打开装进自己的衣兜时，我身上的钱并没有增加一个子儿。”

“那钱包是空的？”

“恰恰相反，里面装满了钞票。”

这引起了我的好奇，于是我给他斟了满满的一杯葡萄酒。

他就开始讲述自己的经历：“当时，我乘火车从斯米纳到苏萨尔去，那是个匪盗经常出没的地区。我坐的是三等车厢，车厢里除我而外，就只有一个衣衫褴褛、正在酣睡的汉子，他的左脸颊上有一块明显的伤疤。从相貌到衣着，这家伙看起来像一个罪犯。我想换一个车厢，可是车厢之间没有连通的门，于是，我只好硬着头皮单独同这个危险的家伙共处 3 个小时。火车行驶在前不挨村、后不着店的荒野，车上的旅客寥寥无几。在这种环境里，要想杀死一个人，然后把尸体从车窗扔下去，简直是小事一桩。”

老头呷了口酒，继续说：“外面的天渐渐黑了下来，我两眼死死盯住车里的警报器。可是，不一会儿我就打起了盹儿。当我迷迷糊糊地睁开眼睛，我不由自主的发出一声惊叫。那的陌生的旅伴正弯腰站在我面前，用那锐利的双眼盯着我，乱蓬蓬的胡须已经触着我的面颊。我吓得一下子蹦起来，想去拉警报器。可是那人却一把抓住我，说：“您不用害怕，我正要请示您允许我坐在您身边，用您的毯子搭一搭我的身子，我感到很冷。”听他这么诚恳地说，我好不容易松了口气，歉疚地挪动了一下身子，让他坐到我身边。

“‘是的，’那人说，‘我多么喜欢做一个小偷啊！我的整个性格，所受的教育和成长的环境，都注定我特别适合这一职业。可是……我不能去偷，’”

“‘是什么阻止你去偷呢？’我好奇地问。”

“‘长着这样一副相貌，我怎么能够去偷呢？无论我走到哪里，大家都提防着我，要是碰巧附近人的东西正好被偷了，不用说，第一个被怀疑的对象就是我。’”

“我瞅着他那张窃贼一样的面孔，脑海里闪出了一个鬼主意：我要是试一试把这个不走运的人的钱包偷过来，那将是一个多么精彩的恶作剧啊！于是我不动声色地把手悄悄地伸过去，上帝保佑！几分钟后，窃贼那鼓鼓地钱包就被放进了我右边衣袋。不一会儿，火车停了下来，我的旅伴竟免了我再劳神去换车厢，他站起来对我说：‘我到家了，谢谢您，祝您旅行愉快！’”

“我等他下了车，急忙从衣兜里掏出偷来的钱包。一见那钱包，我顿时目瞪口呆：我手里拿的正是我自己的钱包。那家伙趁我听他诉苦的当儿，神不知鬼不觉地把我的钱包偷走了。幸好趁他不注意进，我又把它偷了回来。”

“这是我一辈子惟一的偷窃行为。钱包偷到手了，可我的钱并没有因此而增加一分。您看见了吧，我并没有骗你。”

老头讲完故事，我附加了几句客套话，站起来大大方方地付了酒钱，转身就走了。我这样做，完全是有原因的：在他向我讲述自己偷窃经历时，我已用我那训练有素的灵巧手指，将他的钱包拈过来装进了自己的衣兜。我急切地想知道那钱包里究竟有多少钱。

我相信，老头所说的那种巧遇，这次绝不会重演。我肯定不会从自己的衣兜里掏出自已的钱包来，因为我身上从来不带钱包。拐过一个街角，我把手伸进自己的衣袋。天啊！里面什么也没有！这老家伙太鬼了！他第二次偷回了自己的钱包。

第二次？谁知道他自己偷了自己多少回呢？


# 最担心的是你

作者：佚名

清晨，我开着车去公司，突然一辆车紧贴着从旁边超了过去，只听“吱”的一声，我的车门被刮出一道长长的划痕。

我把车停到路边，正想骂那个“冒失鬼”，看到那辆车里面钻出一个神色慌张的年轻女人。她面如土色，匆匆向我走来。

“实在对不起。我刚学会开车，技术还不熟练。我会赔偿您的一切损失。”一到跟前，她就忙不迭地认错。可她一回头，发现自己的新车也“挂了彩”，前胎也瘪了，女人突然失声痛哭起来。

“你怎么了？”我吓了一跳，忙说：“别哭啊，别人还认为我欺负你呢！”

“这是两天前我丈夫买的新车。”女人抽泣着说。原来她觉得新车刚买了两天，居然就被自己弄坏，实在无法面对整日在外辛苦挣钱的丈夫，她越说越伤心，眼泪止都止不住。

看到女人这样，我不由得产生了同情，但不管怎样，事故报告书上需要填写驾驶证和车辆保险的相关信息，先得解决正事。她打开储物箱，拿出装有相关证件材料的信封。

“这是我丈夫为我应对突发状况准备的。”女人一边说，一边从信封里往外拿材料。

看到材料的一刹那，女人的眼泪又一次流了下来。只见在她拿出的材料中，第一页上用粗笔大大地写着这样一句话：“亲爱的，万一你真出了事故，一定要记住：我最担心、最爱的，并不是这辆车，而是你。”


# 客厅里的爆炸

作者：白小易

主人沏好茶，把茶碗放在客人面前的小几上，盖上盖儿。当然还带着那甜脆的碰击声。接着，主人又想起了什么。随手把暖瓶往地上一搁。他匆匆进了里屋，而且马上传出开柜门和翻东西的声响。

做客的父女俩待在客厅里，十岁的女儿站在窗户那儿看花。父亲的手指刚刚触到茶碗那细细的把儿——忽然，叭的一响，跟着是绝望的碎裂声。

——地板上暖瓶倒了。女孩也吓了一跳，猛地回过头来。事情尽管极简单，但这近乎是一个奇迹，父女俩一点儿也没碰它。的的确确没碰它。而主人把它放在那儿时，虽然有点摇晃，可是并没有马上就倒哇。

暖瓶的爆炸声把主人从里屋揪了出来。他的手里攥着一盒方糖。一进客厅，主人下意识地瞅着热气腾腾的地板，脱口说了声：

“没关系！没关系！”

那父亲似乎马上要做出什么表示，但他控制住了。

“太对不起了。”他说，“我把它碰了。”

“没关系。”主人又一次表示这无所谓。

从主人家出来，女儿问：“爸，是你碰的吗？”

“……我离得最近。”爸爸说。

“可你没碰！那会儿我刚巧在瞧你玻璃上的影儿。你一动也没动。”

爸爸笑了：“那你说怎么办？”

“暖瓶是自己倒的！地板不平。李叔叔放下时就晃，晃来晃去就倒了。爸，你为啥说是你……”

“这，你李叔叔怎么能看见？”

“可以告诉他呀。”

“不行啊，孩子。”爸爸说，“还是说我碰的听起来更顺溜些。有时候，你简直不明白是怎么回事。你说的越是真的，也越像假的，越让人不能相信。”

女儿沉默了许久：

“只能这样吗？”

“只好这样。”


# 假如是你的话

作者：都筑道夫

“这个戒指真的白给我？大概是人造钻石吧，但人造钻石这么大也妙极了。”

“是真的钻石。不嫌弃的话，请戴上试试。”

推销员交出了戒指盒。女的双颊一红，捏起了戒指。推销员按住这只手，说道：“请等一下，太太。不行。我不能说谎。”

“还是有什么条件吧？这么贵重的东西，不可能白给嘛。”

“说实在的，这不是平常的戒指。是一个遥控开关。我不是这个地球的人。是从一个遥远的星球来的。我们那个星球，由于人口过剩，眼看要爆发危机，不得不采取非常措施。结果，决定杀死五百万无用之人。可是谁也不肯按执行死刑的开关。因此派我到这里来。一戴上这只戒指，立刻要死五百万人。这颗钻石可以说是执行死刑的报酬。对不起，太太。”

“尽开玩笑。到底是给还是不给？”

“肯戴的就奉送。不过，要等我回去以后再戴。”

推销员把戒指留在女的手中，跳出门外。女的手拿戒指端详了片刻。然后——假如是你的话，怎么办呢？


# 愿你慢慢长大

作者：刘瑜

亲爱的小布谷：

今年六一儿童节，正好是你满百天的日子。

当我写下“百天”这个字眼的时候，着实被它吓了一跳——一个人竟然可以这样小，小到以天计。在过去 100 天里，你像个小魔术师一样，每天变出一堆糖果给爸爸妈妈吃。如果没有你，这 100 天，就会像它之前的 100 天，以及它之后的 100 天一样，陷入混沌的时间之流，绵绵不绝而不知所终。

就在几天前，妈妈和一个阿姨聊天，她问我：为什么你决定要孩子？我用了一个很常见也很偷懒的回答：为了让人生更完整。她反问：这岂不是很自私？用别人的生命来使你的生命更“完整”？是啊，我想她是对的。但我想不出一个不自私的生孩子的理由。

古人说：不孝有三，无后为大，不自私吗？现代人说：“我喜欢小孩”，不自私吗？生物学家说“为了人类的繁衍”，哎呀，听上去多么神圣，但也不过是将一个人的自私替换成了一个物种甚至一群基因的自私而已。

对了，有个叫道金斯的英国老头写过一本书叫《自私的基因》，你长大了一定要找来这本书读读，你还可以找来他的其他书读读，妈妈希望你以后是个爱科学的孩子，当然妈妈也希望你在爱科学的同时，能够找到自己的方式挣脱虚无。

因为生孩子是件很“自私”的事情，所以母亲节那天，看到铺天盖地“感谢母亲”、“伟大的母爱”之类的口号时，我只觉得不安甚至难堪。我一直有个不太正确的看法：母亲对孩子的爱，不过是她为生孩子这个选择承担后果而已，谈不上什么“伟大”。

以前我不是母亲的时候不敢说这话，现在终于可以坦然说出来了。甚至，我想，应该被感谢的是孩子，是他们让父母的生命“更完整”，让他们的虚空有所寄托，让他们体验到生命层层开放的神秘与欣喜，最重要的是，让他们体验到尽情地爱——那是一种自由，不是吗？能够放下所有戒备去信马由缰地爱，那简直是最大的自由。作为母亲，我感谢你给我这种自由。

也因为生孩子是件自私的事情，我不敢对你的未来有什么“寄望”。没有几个汉语词汇比“望子成龙”更令我不安，事实上这四个字简直令我感到愤怒：有本事你自己“成龙”好了，为什么要望子成龙？如果汉语里有个成语叫“望爸成龙”或者“望妈成龙”，当父母的会不会觉得很无礼？

所以，小布谷，等你长大，如果你想当一个华尔街的银行家，那就去努力吧，但如果你仅仅想当一个面包师，那也不错。如果你想从政，只要出于恰当的理由，妈妈一定支持，但如果你只想做个动物园饲养员，那也挺好。

我所希望的只是，在成长的过程中，你能幸运地找到自己的梦想——不是每个人都能找到人生的方向感，又恰好拥有与这个梦想相匹配的能力——也不是每个人都有与其梦想成比例的能力。

是的，我祈祷你能“成功”，但我所理解的成功，是一个人对自己所做的事情有敬畏与热情——在妈妈看来，一个每天早上起床都觉得上班是个负担的律师，并不比一个骄傲地对顾客说“看，这个发型剪得漂亮吧”的理发师更加成功。

但是，对你的“成就”无所寄望并不等于对你的品格无所寄望。妈妈希望你来到这个世界不是白来一趟，能有愿望和能力领略它波光潋滟的好，并以自己的好来成全它的更好。

妈妈相信人的本质是无穷绽放，人的尊严体现在向着真善美无尽奔跑。

所以，我希望你是个有求知欲的人，大到“宇宙之外是什么”，小到“我每天拉的屎冲下马桶后去了哪里”，都可以引起你的好奇心；

我希望你是个有同情心的人，对他人的痛苦——哪怕是动物的痛苦——抱有最大程度的想象力，因而对任何形式的伤害抱有最大程度的戒备心；

我希望你是个有责任感的人，意识到我们所拥有的自由、和平、公正就像我们拥有的房子车子一样，它们既非从天而降，也非一劳永逸，需要我们每个人去努力追求与奋力呵护；

我希望你有勇气，能够在强权、暴力、诱惑、舆论甚至小圈子的温暖面前坚持说出“那个皇帝其实并没有穿什么新衣”；

我希望你敏感，能够捕捉到美与不美之间势不两立的差异，能够在博物馆和音乐厅之外、生活层峦叠嶂的细节里发现艺术；

作为一个女孩，我还希望你有梦想，你的青春与人生不仅仅为爱情和婚姻所定义。这个清单已经太长了是吗？

对品格的寄望也是一种苛刻是吗？好吧，与其说妈妈希望你成为那样的人，不如说妈妈希望你能和妈妈相互勉励，帮助对方成为那样的人。

小布谷，愿你慢慢长大。

愿你有好运气，如果没有，愿你在不幸中学会慈悲。

愿你被很多人爱，如果没有，愿你在寂寞中学会宽容。

愿你一生一世每天都可以睡到自然醒。


# 民意与伪民意

作者：刘瑜

在我听到的各种为“大跃进”辩护的言论中，有一类是这样的：当时人民的积极性很高啊，大炼钢铁一拥而上，人民公社热火朝天，多快好省建设社会主义，那是民意！

对，还有人在给“大跃进”辩护，话说这是 21 世纪。

同理当然也可以运用于“反右”、“文革”等。如果我们能穿越时空隧道，跑到 1957 年 10 月的中国做一个民意测验，问民众要不要引蛇出洞揭批反动“右派”，测验结果多半说是“要”。或者穿越到 1967 年 1 月去做一个民意测验，问民众应该不应该修理“走资派”，给他们戴高帽游街批斗，估计民意也会万众一心地说：应该！岂止“应该”，他们还会在调查表里找有没有“再踏上一只脚”这一选项。

不奇怪。1936 年到苏联去，“大清洗”也是民意。1939 年到德国去，打波兰也是民意。

现在，假设我们是一场选美大赛中的裁判。主持人指着台上光芒四射的美女宣布：“你们有三个选择：你可以选择 A，或者 A，或者 A。”

哇，琳琅满目耶。

什么？你想选择 B？好的，谢谢你选择 A。什么？你想选择 B？好的，谢谢你选择 A。

有一种民意叫伪民意。在一个多元意见、选择自由不可能的环境里，民意只能被认作是伪民意。即使它是真民意，你也无从知道它是不是真民意。

伪民意未必是假民意。它未必是数据舞弊，比如把 35％ 的支持率用橡皮擦擦掉，改成 95% 。它也未必全然是政治恐吓的产物，虽然恐吓往往是其要素之一。在特定时刻，人们可能是真心地想要大炼钢铁、搞人民公社、支持“大清洗”、支持军国主义。1958 年，当公社社员坐在堆出来的麦地上拍丰收卫星的照片时，观察他们脸上的笑容，笑得那可是货真价实。1966 年，当红卫兵们将皮鞭抽向“地富反坏右”时，他们眼里的熊熊怒火，肯定也不是伪劣产品。

鉴定民意的真伪，标准不在于民众选择的那一刻是不是真诚，而在于他们在形成意见时讨论是否自由、观念可否多元、信息是否充分。没有自由讨论基础的民意，就像一年四季只吹西北风的树，长歪了毫不奇怪。如果美女 A 盛装在镁光灯下从观众面前惊艳地飘过，而美女 B 只能戴着口罩站在舞台后方黑漆漆的角落里。就是百分之百的观众百分之百真诚地选择了美女 A 为选美冠军，那能说明什么呢？说明那个镁光灯质量不错，以及那个口罩还挺严实。

最近我读到一篇关于“中国人民主观”的文章，就给我这种印象。这篇文章告诉我们，调查显示，中国人的民主观是“家长式”的，而不是“自由式”的。也就是说，在中国人看来，领导为老百姓着想，那就是民主了，民众自己犯不着参与到政治决策过程当中去。民众自己参与到决策过程中去，那是“自由式”民主，咱们不吃那一套。

既然是民意调查的结果，那数据肯定错不了。问题在于，如果被调查者天天生活在家长式民主里，每天听到的都是家长如何可亲可信可敬，却从未见过其他式民主长什么样，信息不对称不充分，这样的调查能说明什么呢？你说，让你选你爱吃猪肉还是爱吃恐龙肉，你怎么选呢？

小说《美丽新世界》里，福特纪元的统治者发明了一种“睡梦教育”，就是在本国人民睡着时不断地向他们广播重复信息。比如，“苹果是个坏东西”、“苹果是个坏东西”、“苹果是个坏东西”……等睡梦中的人们醒过来时，他们会伸着懒腰揉着双眼，喃喃自语：苹果是个坏东西。

当然制造伪民意不仅仅依靠宣传，还可以依靠贿赂：凡是选择 A 的，可以得到夏威夷浪漫之旅机票两张哦。还有煽情也很重要：从前，有一个美女叫 A，她来自于一个贫苦家庭，而另一个丑女叫 B，她的爸爸叫李刚……

1953 年 9 月的政协会议上，梁漱溟发言批评政府的农村政策，说工业化大刀阔斧，农村却被忽视，毛主席听了很不高兴，说梁是野心家、伪君子、以及“用笔杀人的杀人犯”。不知好歹的梁漱溟较起真了，非要把事情讲清楚，说要看看毛主席有没有把话听完的雅量。毛主席还没彻底表态呢，台下群众不答应了：民主权利不给反动分子！梁漱溟滚下台来！停止他的胡言乱语！……梁漱溟赖着不走，不肯下台去，固执地跟毛主席要“雅量”。最后，会议只好用举手表决的方式来决定他是否有说下去的权利。

表决结果是什么呢？给大家一个提示：建国前三年，大约有两百万反革命分子给咔嚓了，在此次政协会议以前，有过镇反运动，三反运动，五反运动，批武训运动，土改中的批斗运动和诉苦运动，延安整风中的思想改造运动以及抢救运动，苏区的镇反运动。现在，你们猜，这次表决结果会是什么呢？


# 婚姻中没有天堂

作者：周国平

好的婚姻是人间，坏的婚姻是地狱，别想到婚姻中寻找天堂。

人终究是要生活在人间的，而人间也自有人间的乐趣，为天堂所不具有。

恋爱时闭着的眼睛，结婚使它睁开了。恋爱时披着的服饰，结婚把它脱掉了。她和他惊讶了：“原来你是这样的？”接着气愤了：“原来你是这样的！”而事实上的他和她，诚然比从前想象的差些，却要比现在发现的好些。

结婚是一个信号，表明两个人如胶似漆仿佛融成了一体的热恋有它的极限，然后就要降温，适当拉开距离，重新成为两个独立的人，携起手来走人生的路。然而，人们往往误解了这个信号，反而以为结了婚更是一体了，结果纠纷不断。

人真是什么都能习惯，甚至能习惯和一个与自己完全不同的人生活一辈子。

习惯真是有一种不可思议的力量，甚至能使夫妇两人的面容也渐渐变得相似。

正像恋爱能激发灵感一样，婚姻会磨损才智。家庭幸福是一种动物式的满足状态。要求两个人天天生活在一起，既融洽相处，又保持独特，未免太苛求了。

在婚姻这部人间乐曲中，小争吵乃是必有的音符，倘若没有，我们就要赞叹它是天上的仙曲了，或者就要怀疑它是否已经临近曲终人散了。

在多数情况下，婚姻生活是恩爱和争吵的交替，因比例不同而分为幸福与不幸。恩爱将孤独催眠，争吵又将孤独击昏，两者之间的间歇何其短暂，孤独来不及苏醒。

婚姻的后果之一是失去孤独的心境。至于是幸还是不幸，全看你内心是否有孤独的需要。

婚姻有一个最大的弊病，就是对独处造成威胁。对于一个珍爱心灵生活的人来说，独处无疑是一种神圣的需要。不过，如果双方都能够领会此种需要，并且做出适当的安排，我相信是可以把婚姻对独处的威胁减低到最小限度的。

婚姻中的一个原则：不要企图改变对方。

两口子争吵，多半是因为性格的差异，比如你性子急，我性子慢，你细心，我粗心，诸如此类。吵多了，便会有怨恨，责备对方总也改不了。可是，人的性格是难变的，只能互相适应，民间的智慧称作磨合。仔细分析，比起性格差异来，要对方改变的企图是争吵的更重要原因。如果承认差异，在此基础上各方调整自己的态度，许多争吵都可以平息。

在夫妻吵架中没有胜利者，结局不是握手言和，就是两败俱伤。

把自己当作人质，通过折磨自己使对方屈服，是夫妇之间争吵经常使用的喜剧性手段。一旦这手段失灵，悲剧就要拉开帷幕了。

“看来，要使丈夫品行端正，必须家有悍妻才行。”

“那只会使丈夫在别的坏品行之外，再加上一个坏品行：撒谎。”

“我们两人都变傻了。”

“这是我们婚姻美满的可靠标志。”


# 一种深久的不安

作者：乔叶

有时候，走在街上，看见穿得很破的收废品的老人，骑着锈迹斑斑的三轮车，摇着牛皮纸扎成的拨浪鼓，在绿草如茵的大街上，一脸灰尘，我就会觉得不安。看见卖水果的小贩，小心地拎起一串葡萄，把那些裂了口的果子仔细地摘下，然后把它们最大最好的那一面朝外码好，在深秋的薄暮里用芭蕉扇赶着聚拢过来的蚊蝇，我也会觉得不安。看见人力车夫坐在树荫下，寂寞地抽着烟，眼神却毫不懈怠地关注着来来往往的人流，仿佛要在第一时间的信息里捕捉到他们的乘客，我还会觉得不安。

我不知道他们的名字，每月赚多少，有几个孩子，住在什么地方。除了从表象上对他们职业生活有一点认识，我对他们一无所知。可我就是无法抑制自己对他们的这种不安。他们也是有幸福的，我想。生意顺畅的时候，年节团聚的时候，雨天憩息在家里喝点小酒的时候……我相信他们的快乐，也欣赏他们的享受，可我还是感到不安。而我不安的原因听起来竟是这样的矫情和可笑——因为我的物质生活比他们富足。

精神生活充满了主观性和不确定性，是不能比较的。我知道。可物质生活上我确实比他们富足。每当我掏出钱夹去消费时，就不由得会想到他们。一件专卖店里的名牌 T 恤，一道豪华饭店里的特色佳肴，一辆已经在路边等候的帕萨特出租车……每当我把目光投向这些昂贵的事物上时，总有些莫名其妙的忐忑和心虚，仿佛我在无形中欠了他们什么，而不能无所顾忌地去花这些其实是自己一分一角挣来的钱。

有很多人的物质生活都比他们好，也比我好，我知道。我只是平民百姓中的一分子。然而即使是平民百姓，也有三六九等。我不是最低的一等，也不是最高的一等。作为最低等时，我一定不会甘心。但是当我看到真的还有那么多人在我的界线之下生活时，我却无法对自己理直气壮地说：“花自己的钱，想他们干什么，比你过得好的人多着呢。”

似乎是有些神经，有些自作自受。仿佛他们都是我多年以前的亲人，我今天的生活是踩在他们的肩膀上才拥有的。可细细想来，难道不是吗？我的上几辈的亲人中谁没有和他们一样在最狭窄的空间里挣扎过？谁不是和他们一样为了最基本的生计奉献着自己最浓稠的汗水？他们中有多少人敢去问津“梦特娇”的标价？有多少人摸过五星级酒店里的紫檀雕筷？有多少人会识别“蓝鸟”和“奔驰”的标志？作为一个在农村长大的孩子，我怎么能够容许自己这么快就割断我和他们之间最本质的那种血脉关联？

我做不到。鲁迅说过，生存不是苟活，温饱不是奢侈，发展不是放纵。而我已经看到有太多的人正在奢侈和放纵中苟活着，我不想这样。我常常会问自己：有必要穿这么好的衣服吗？有必要吃这么贵的菜吗？有必要坐这么好的车吗？答案常常不是肯定的。那么，我就会坚定地和这些东西远离，去作一种最经济的选择。

我不评价别人的消费。这是个性化的时代，在法律允许的范围内，每个人都有权利选择自己的生活方式。所以，我只尽力来控制自己，不让自己的欲望随着时尚的标准而高涨。仿佛只有这样，自己才不会离那些底层的人们更远，同时也让心灵获得最质朴的感知和最踏实的抚慰。


# 非走不可的弯路

作者：张爱玲

在青春的路口，曾经有那么一条小路若隐若现，召唤着我。

母亲拦住我：“那条路走不得。”我不信。

“我就是从那条路走过来的，你还有什么不信？”

“既然你能从那条路上走过来，我为什么不能？”

“我不想让你走弯路。”

“但是我喜欢，而且我不怕。”

母亲心疼地看我好久，然后叹口气：“好吧，你这个倔强的孩子，那条路很难走，一路小心。”

上路后，我发现母亲没有骗我，那的确是条弯路，我碰壁，摔跟头，有时碰得头破血流，但我不停地走，终于走过来了。

坐下来喘息的时候，我看见一个朋友，自然很年轻，正站在我当年的路口，我忍不住喊：“那路走不得。”她不信。

“我母亲就是从那条路走过来的，我也是。”

“既然你们都从那条路上走过来了，我为什么不能？”

“我不想让你走同样的弯路。”

“但是我喜欢。”

我看了看她，看了看自己，然后笑了：“一路小心。”

我很感激她，她让我发现自己不再年轻，已经开始扮演“过来人”的角色，同时患有“过来人”常患的“拦路癖”。

在人生的路上，有一条路每一个人非走不可，那就是年轻时候的弯路。不摔跟头，不碰壁，不碰个头破血流，怎能炼出钢筋铁骨，怎能长大呢？


# 单调产生的快乐

作者：费尔南多 · 佩索阿

大多数的人以其愚笨生活在他们的生活之中，而这一回，愚笨中的智慧更使我惊讶。

显而易见，普通生活的单调是极其可怕的。我在这个普通的餐馆吃中饭，看见柜台后面的厨师，还有右边的老侍者，正在像对待这里所有的客人一样为我服务，我相信，他这样做已经有三十年了。这些人过着一种怎样的生活？即便过上四十年，那个厨师还是差不多在厨房里度过他的每一天，有一点点休息，相对来说少了点睡眠，有时候去他的村子打一转，回来时拖沓了一点但无须愧疚。他慢慢地积攒着自己慢慢赚来的钱，不打算花掉的钱。他将要落病并且不得不放弃（永远地）他的厨房，进入他在 G 省买下的墓地。他在里斯本活了四十年，但他从没有去过 R 区，没有去过戏院，只去过一次 C 区（那里的马戏小丑嵌入他生活的深处历久弥新）。他结婚了，为什么结婚和怎样结的婚？我一无所知。他有四个儿子和一个女儿。当他冲着我的餐桌把身子斜靠在柜台上，他的微笑传达着一种伟大的、庄重的、充实的快乐。他并没有装模作样，没有任何理由这样做。他之所以显得快乐，是因为他确实快乐。

那个刚刚给我上了咖啡的老侍者又怎么样呢？在他的一生中，他数以万次地这样上咖啡，活得与厨师无异，唯一的区别是他干活的餐厅与其他人干活的厨房有四、五码之遥。这样说当然撇开了另一些小区别，诸如他有两个小孩而不是五个小孩，他更经常地去 G 市，他比厨师更了解里斯本（如同更了解 O 市，他在那里呆过四年），他同样是充实的。

我带着真正的惊骇，再一次观看那些生类的全景，几乎为他们感到恐惧、悲伤以及惊乱。我发现那些没有感到恐惧、悲伤以及惊乱的人，正好是生活在他们生活中并且最有权利这样做的人。文学想象的核心错误，就是这样的观念：别人都像我们并且必定像我们一样感受。人类的幸运在于，每一个人都是他们自己，只有天才才被赋予成为别人的能力。

一切事物最终来说都是相对的。街头一个小小的事故，把餐馆厨师吸引到门口，此时的他，比我寻思一个最具原创性的念头，比我阅读一本最好的书或者欣悦于一些无用的梦，有更多的娱乐。而且，如果生活本质上是单调的，那么真理就是：他比我更容易也更好地逃出了单调。真理不属于任何人，因此他并不比我更多地拥有真理，但他拥有快乐。

聪明人把他的生活变得单调，以便使最小的事故都富有伟大的意义。任何历险的猎手在打了三只狮子以后都会丧失猎狮的兴致，而在我单调的厨师那里，他目击的所有街头斗殴都能令他赏心悦目，从中获益。对于从来没有离开过里斯本的人来说，驾驶电车去一趟 B 区就像无终无止的远游，如果有一天让他探访 S 市，他也许会觉得去了火星。在另一方面，遍游了全球的旅行者，走出方圆五千英里以外就再也不能发现什么新的东西。他总是看见新的东西。哪里有新奇，哪里就有见多不怪的厌倦，而后者总是毁灭了前者。真正的聪明人，都能够从他自己的躺椅里欣赏整个世界的壮景，无须同任何人说话，无须了解任何阅读的方法，他仅仅需要知道如何运用自己的五种感官，还有一颗灵魂里纯真的悲哀。

一个人为了摆脱他的单调，必须使存在单调化。一个人必须使每一天都如此平常不觉，那么在最微小的事故中才有欢娱可供探测。在我日复一日的工作当中，充满着乏味、重复、不得要领的事情，幻象使我神不守舍：遥远海岛的残梦，在另一个时代的花园大道上举行的种种聚会，不同的景象，不同的感觉，另一个不同的我。但是，平心而论，我意识到如果哪一天我真的得到了那一切，它们就会无一例外地不再是我的了。

事实是，V 先生的比任何梦中国王更有价值；道拉多雷斯大街上的办公室比所有虚构花园里的宽广大道更有价值。因为正是 V 先生，才使我能够享乐于国王梦；正是因为道拉多雷斯大街，才使我能够享乐于内心中种种不可能存在的山光水色。如果梦中的国王属于我，我还有何可梦？如果我拥有那些绝无可能的山光水色，那么还有什么东西可为幻影？

我一直被这种单调护佑。相同日子的乏味雷同，我不可区分的今天和昨天，使我得以开心地享乐于迷人时间的飞逝，还有眼前世间任意的流变，还有大街下面什么地方源源送来的笑浪，夜间办公室关闭时巨大的自由感，我余生岁月的无穷无尽。

因为我是无，我才能够想象我自己是一切。如果我是某个人，我就不能够进入想象中的这个人。一个会计助理可以把他自己想象成罗马国王，但英国国王不能，因为英国国王已经失去了把自己梦想成另一个国王的能力。他的现实限制他的感觉。


# 我只是讨厌屈服

作者：柴静

10:03，北京市第一中级人民法院。

郝劲松坐在原告的位子上开口说话，“审判长，通知我的开庭时间是 10:00，被告迟到，我是否能得到合理解释？”

审判长看他一眼，说“现在你先听从法庭的程序”，冲书记员挥了下手。

书记员立刻跑出去大声叫“北京地铁公司！北京地铁公司！”

片刻，两位男士夹着公文包，匆匆入门，在被告席上落座。

原被告双方目光交汇的一刹那，法庭非常安静。我明白了郝劲松为什么说“不管你有多强大，包括一个国家部委，当你被告上法庭的时候，你是被告，我是原告，大家坐在对面，中间是法官。你和我是平等的。”

这是一场关于五角钱的官司，他在地铁使用了收费厕所，认为这收五角钱不合理。所以把北京地铁公司告上法庭。

两年多，他打了 7 场这样的官司---他在火车餐车上买一瓶水，要发票。

列车员都笑了“火车自古没有发票”。

他于是起诉铁道部，国家税务总局，。。。一次一次。

“在强大的力量面前人们往往除了服从别无选择，但是我不愿意。”他说。“我要把他们拖上战场，我不一定能赢，但我会让他们觉得痛，让他们害怕有十几二十几个象我这样的人站出来，让他们因为害怕而迅速地改变。”

“钱数这么小，很多人觉得失去它并不可惜”我说。

“今天你可以失去获得它的权利，你不抗争，明天你同样会失去更多的权利，人身权，财产权，包括土地、房屋。中国现在这种状况不是偶然造成的，而是长期的温水煮青蛙的一个结果，大家会觉得农民的土地被侵占了与我何干？火车不开发票，偷漏税与我何干？别人的房屋被强行拆迁与我何干？有一天，这些事情都会落在你的身上。”

“但是一个人的力量能改变什么呢？”

“看看罗莎，帕克斯，整个世界为之改变”他说。

帕克斯是美国的一个黑人女裁缝，1955 年 12 月 1 日，在蒙哥马利市，42 岁的她在一辆公共汽车上就座。按照当时的惯例，美国南部公共汽车上实行种族隔离，座位分为前后两部分，白人坐前排，黑人坐后排。

那天晚上人很挤，白人座位已占满，有白人男子要求坐在黑人部分最前排的她让座，遭到了拒绝。

当司机要求乃至以叫警察恐吓黑人让座时，坐在前排的其它三个黑人站了起来，唯独帕克斯倔强地牢坐不起。

如果是一个孩子或是老人，也许她会站起来，但这次，她厌烦了她和其它美国黑人每天在生活中所受到的不公平对待，她说：“我只是讨厌屈服”。

她成了 50 年代美国第一个拒绝给白人让座的黑人。然后她因公然藐视白人而遭逮捕。

她的被捕引发了蒙哥马利市长达 381 天的黑人抵制公交车运动，组织者是当时仍名不见经传的一名牧师马丁·路德·金，这个名字后来被冠以反种族隔离斗士和诺贝尔和平奖得主的荣誉。这场运动的结果，是 1956 年最高法院裁决禁止公车上的“黑白隔离”，帕克斯从此被尊为美国“民权运动之母”。

事实上，她并没有组织或领导 50 年前那场民权运动，她只是在适当的时刻表现了一个平凡人的勇气，而这种勇气迫使整个国家重新审视并改变了原有的社会道德体系。

五十年后，美国国务卿赖斯说“没有她，我不可能站在这里”

“你以谁的名义在诉讼？”我问郝劲松。

“公民。”

“公民和普通人的区别是什么？”

“能独立地表达自己的观点，却不傲慢，对政治表示服从，却不卑躬屈膝。能积极的参与国家的政策，看到弱者知道同情，看到邪恶知道愤怒，这我认为他才算是一个真正的公民。”

他打赢铁路发票的官司后，很多人以为他会和铁路结下梁子。

但他说起他乘车时，乘务长会亲自端来饭菜，问他“发票你现在要还是吃完再说？”

“你靠什么赢得尊重？”我问。

“靠我为了自己权利所做的斗争。权利是用来伸张的，否则权利只是一张纸。”他说。

我停顿了一下，问他最后一个问题“你想要一个什么样的世界？”

这个 34 岁的年青人说，“我想要宪法赋予我的那个世界。”


# 跳槽只为“软福利”

作者：王小柔

很长时间没联系的一个老同学忽然来了电话，说她又跳槽了，一定要让我去新单位看看，因为她所在的写字楼洗手间里安装了全套美标的洁具，还有名牌洗手液、七分钱一张的吸水纸，最可贵的是马桶旁边那两卷厚厚的舒爽卫生纸永远用不完。我特别惊讶，问她：“你不会是因为厕所跳槽的吧？”她底气十足地回答：“不是才怪！”我如约到了她的写字楼，那里确实气派十足：电梯宽大无比，每层都有可供商务洽谈的柔软沙发，旁边就是整面落地玻璃，而全楼最奢华的就是厕所。据说我的同学只是基层员工，居然拥有偌大的专属办公室，还有几盆精致的盆栽。

我的同学是个工作上的拼命三郎，但她对环境的要求特别苛刻。上次跳槽据说是因为写字楼里的电梯，就是那种空间狭窄、能同时容纳 15 个人、满员时站着如同接吻姿势的廉价电梯。平时乘电梯的人并不多，但每到中午 11 点大厦里食堂开始卖饭的点儿，电梯就忙坏了，几乎每层必停，一群群刚吃完和正准备吃的人进进出出，电梯里充满了一股浓郁的菜味儿，有人在咂吧嘴、有人在打嗝、有人在抖搂饭盒里的水，搞得我同学很长时间一进电梯就犯恶心，都快成生理上的条件反射了。后来她发现每到下午，电梯里总会出现一些光着脚趿着拖鞋，肩上扛着毛巾的人一层层找能洗澡的卫生间，那一刻电梯里满是洗头水的味儿，弄得她经常疑惑自己是不是在一家洗浴中心里办公。这些她都忍了，最让她受不了的是，厕所里的手纸经常不知道被谁当单位福利拿回了家，总是在她疏忽自带卫生纸的时候，眼前只剩下一个光秃秃的空盒。所以在一个阳光明媚的下午，当她绝望地一把提起裤子，想到的只有一个词：跳槽！

她之后就到了这家对着装要求极为严格的外企，每天早晨花一刻钟化一个 OL 妆，粉底霜、收缩水、精华素、腮红、眼影、香水一个都不能少，即便这样还生怕自己配不上这个大楼的光鲜。这里，电梯大了，菜味换成了化妆品味，她觉得这样的味道才适合自己，就连她洗完手不小心滴落在大理石台上的水珠，都有不知从哪儿冒出来的服务生及时擦去。

在能够享用自带七分钱一张吸水纸的厕所以后，我的同学觉得每天上班简直成了妙不可言的人生享受。虽然她的手机随时都会响起，虽然她随时都要上网接收老板指令，哪怕她现在在睡觉、在逛街或者在上厕所，都要时刻准备着接收指令，但是她仍然以打了鸡血的姿态投入工作。

人的职场幸福感，其实就是这么简单、这么不可理喻，很大程度往往与薪水无关，它源于看不见却又无处不在的“软福利”。软福利可能只是向上司的表达权得到尊重、诉求得以重视、向上升迁的愿望有更多实现的可能性。又或许只是公司给你提供的种种细微便利，譬如有的公司会给员工提供理发、修鞋等杂七杂八的服务，免费提供早餐、旅游休假，又或者是一趟班车让你早早回家与老人共享天伦。对我的同学来说，厕所福利虽小，但它是促进身心健康的必备法宝，因为没人喜欢从繁重的工作中暂时解脱后又走进一个又小又脏又臭的空间。

我的同学是个闲不住的人，总叫嚣着还要再跳槽，却迟迟没跳。我想，真正挽留住她的不是职位、薪金，而是这里的厕所，当然，这个秘密她的老板未必知道。


# 你的阅读造就了你

作者：沈奇岚

亲爱的：

大学生活还是让你不满意么？课程枯燥，老师敷衍，有人创业，有人恋爱。你心志不低，想要一份光辉的未来。可是，你说大一过得浑浑噩噩，大二也在稀里糊涂中即将过去。每天醒来你都告诉自己要努力奋斗，可是每一天过去的时候都好像一事无成。你看励志书，里面说目标明确、意志坚定就可以达到目标。你总是做不到。

我告诉你一个真相：如果你真的想在经济方面有所作为，那么你就看错书了。想在经济方面有所建树，你首先应该看得是专业书。我今天想和你聊的是了解世界的方法论。不知道你是否也有这样的感觉：这个信息爆炸的世界，又是一个信息极度不对称的世界。网络上总有无穷的链接吸引着自己：这个明星有新的男朋友了，那个政客说了些什么了，新的恶搞视频让你哈哈大笑，新的电子产品让你忍不住一遍一遍搜索……你了解那么多新鲜有趣的事物，可是亲爱的你，这些并不能帮助你更了解这个世界。因为你始终没有用自己的标准来筛选信息。你会说，你只看对你而言有趣的信息。亲爱的，你想过吗，你的需求是被制造的，你的趣味也是被引导的，你的追求是被煽动的。如果没有那么多广告说睫毛越长越好看，你可会追求那些睫毛膏？

我绝对赞成女孩子要打扮得漂漂亮亮，让自己赏心悦目。但是更重要的是，善待自己的心灵，懂得喂养自己的大脑。你的时间精力都分散在了这些被煽动的追求上，自然没法去实现自己真正想要的目标。

有个理论叫做“你的阅读造就了你。”如果整天徘徊在明星的博客上，那么更适合你的职业娱乐记者，你说对经济有兴趣，你要看的是学者们的著作，财富人物的访谈或许可以让你心潮澎湃，却不能让你的思想更锐利。

关于文化，你要明白自己是想玩票还是真心热爱文化。如果只是觉得文化是个很好的消遣，那么看看欧洲文艺电影，听听摇滚，翻几本装帧设计精良的小说大概就够了。如果是真心想投身于文化，要做的功课就多了。无论是维基百科还是谷歌还是百度，都远远不够。你要去的地方是博物馆美术馆图书馆，你要看的是最新的世界性艺术杂志，你需要一个志同道合的圈子与你一起交流和创作……

如果你每天起来，心不在焉地上几节课，拿起单词书又放下，你就知道你为什么是现在这个样子了。你根本不喂养你的大脑，那么它自然也不能实现你的愿望。雄心壮志需要一个实际的计划，单靠每天的锵锵誓言是于事无补的。

我不知道和网络时代一起成长的你是否比我更了解世界。我始终觉得世界和以前一样，信息严重不对称。你是否知道你将来要进入的那个世界，你将来所期待的生活里面，有什么等待着你？

对自己的塑造，就在于你如何使用每一分钟。你和时间的关系，就形成了你自己。

和朋友欢聚怡养心灵，参加派对也让人放松神经，在八卦论坛上拍拍板砖也很释放情绪。但那不能成为你生活的全部。

试试看，跟踪自己一个星期，列个“我在看什么”的表格。一周下来，你自然清楚，为什么你现在是这样的一个你。还在大学里的你，实在是得天独厚。有那么好的机会和条件，帮你成为自己想成为的那个你。

曾经看到杨绛说她的读书经历。有人问他，如果三天没有读书，感觉怎样？她说，感觉不好受。如果一周不读书呢？她说：“那么我一周都白活。”

我白活过很多时间，如今有些后悔了。希望你不要重蹈我的覆辙。每天看一点书，你会发现有收获的。

愿你在这个信息爆炸的世界里，找到属于自己的行星轨迹。总会有这样那样的天外陨石来撞击你的轨道的，坚持自己的定力！


# 聪明人和傻子和奴才

作者：鲁迅

奴才总不过是寻人诉苦。只要这样，也只能这样。有一日，他遇到一个聪明人。

“先生！”他悲哀地说，眼泪联成一线，就从眼角上直流下来。“你知道的。我所过的简直不是人的生活。吃的是一天未必有一餐，这一餐又不过是高粱皮，连猪狗都不要吃的，尚且只有一小碗……”

“这实在令人同情。”聪明人也惨然说。

“可不是么！”他高兴了。“可是做工是昼夜无休息：清早担水晚烧饭，上午跑街夜磨面，晴洗衣裳雨张伞，冬烧汽炉夏打扇。半夜要煨银耳，侍候主人耍钱；头钱从来没分，有时还挨皮鞭……。”

“唉唉……”聪明人叹息着，眼圈有些发红，似乎要下泪。

“先生！我这样是敷衍不下去的。我总得另外想法子。可是什么法子呢？……”

“我想，你总会好起来……”

“是么？但愿如此。可是我对先生诉了冤苦，又得你的同情和慰安，已经舒坦得不少了。可见天理没有灭绝……”

但是，不几日，他又不平起来了，仍然寻人去诉苦。

“先生！”他流着眼泪说，“你知道的。我住的简直比猪窝还不如。主人并不将我当人；他对他的叭儿狗还要好到几万倍……”

“混帐！”那人大叫起来，使他吃惊了。那人是一个傻子。

“先生，我住的只是一间破小屋，又湿，又阴，满是臭虫，睡下去就咬得真可以。秽气冲着鼻子，四面又没有一个窗子……”

“你不会要你的主人开一个窗的么？”

“这怎么行？……”

“那么，你带我去看去！”

傻子跟奴才到他屋外，动手就砸那泥墙。

“先生！你干什么？”他大惊地说。

“我给你打开一个窗洞来。”

“这不行！主人要骂的！”

“管他呢！”他仍然砸。

“人来呀！强盗在毁咱们的屋子了！快来呀！迟一点可要打出窟窿来了！……”他哭嚷着，在地上团团地打滚。

一群奴才都出来，将傻子赶走。

听到了喊声，慢慢地最后出来的是主人。

“有强盗要来毁咱们的屋子，我首先叫喊起来，大家一同把他赶走了。”他恭敬而得胜地说。

“你不错。”主人这样夸奖他。

这一天就来了许多慰问的人，聪明人也在内。

“先生。这回因为我有功，主人夸奖了我了。你先前说我总会好起来，实在是有先见之明……。”他大有希望似的高兴地说。

“可不是么……”聪明人也代为高兴似的回答他。


# 你永远有做不完的事

作者：理查德 · 卡尔森

许多人过日子的方式，好像有一个秘密目标，非要把一切事情都做完不可。我们熬夜、早起、不敢放纵逸乐，让我们所爱的人一直等下去。可悲的是，太多人就是因为让他们所爱的人等太久，最后对方终于放弃了这段感情。以前，我就这个样子。我们通常会说服自己，忙得不可开交只是暂时的，一旦做完了该做的事，我们就能平静放松下来，并且心情愉快。事实上，这样的境界永远不会到来，因为旧的事情刚做完，新的立刻接踵而至。

“待办清单”只意味着你有一些事情尚待处理，并不表示你得全部做完。人永远都有没打完的电话、未结束的计划、未完成的工作。事实上，我们可以说，一张写得满满的待办清单才是成功的要素，因为这代表你的时间很宝贵。

不过，不论你是什么大人物，或者在做什么大事，记住，没有什么事比你和你所爱的人的幸福和内心安宁更重要。如果你一直执著于完成所有事情，那永远不会有幸福的感觉！其实，几乎所有的事情都是可以等的，我们的工作中真正属于“紧急”的事少之又少。只要你专心一意地工作，事情都会及时完成的。

我发现，如果我（经常）提醒自己，人生的目的并非完成所有事情，而是去享受生命旅途上的每一步，过着充满爱的生活，我就不太会有执著于非得完成所有事情不可的念头。记住，在你离开人世的那一天，还是会留下未完的事需要别人代劳，而且也一定会有人来代劳的！别浪费了生命的每一分每一秒，再做无谓的惋惜。


# 精神病院里的年轻人

作者：班超

我正在一家精神病院的花园里散步，遇见一个年轻人手捧一本哲学书在专心致志地阅读。他的行为举止正常、身体健康，与其他的病人截然不同。

我坐到他旁边问：“你在这里干什么？”

他看了看我，很是吃惊。当看出我不是医生之后，他回答：“很简单。我父亲，一位才华横溢的律师，他想要我和他一模一样；拥有一家大商场的我叔叔，希望我以他为榜样；我母亲希望我像他敬爱的父亲那样；我姐姐常在我面前把她丈夫树立为成功男人的典范；我哥哥试图把我训练成和他一样优秀的运动员。同样的事情发生在学校里，钢琴老师和英语老师全都确信并断定他们自己是我应该效仿的最好榜样。没有人把我当一个人看待，他们只把我看作他们自己在镜子里的影子。所以，我决定还是住进精神病院了，至少，在这里我能做我自己。”


# 一位短跑运动员的孤独

作者：渡边浩二

我仅仅是为了短跑而诞生的一位男子而已。从我诞生之日起，我的短跑命运就已经决定了，这一点千真万确、毋庸置疑。

我的父母曾是奥运会百米短跑冠军。

可是，我从来就没见过他们。

父亲是我出生很久以前的那个时代的运动员。可是，他创造的世界纪录至今仍未被打破。

母亲是我出生数年前，在体坛上非常活跃的一位运动员。据说她刚过全盛时期就不幸死于非命。

不过，科学家成功地从母亲体内取出了仍存活的卵子，并作为政府的财产存入“卵子银行”。不久，遗传基因电脑管理系统发出了“可以结合”这样一条信息，即“具备了十分匹配的精子和卵子”。

也就是说：计算机把一直冷冻保存的父亲的精子和前不久登记的母亲的卵子的遗传基因数据计算后，得出了如下结论——能够孕育出一个具有百米跑最佳素质的婴儿。

为了能创造出百米的最好成绩，计算机就理想的人体条件进行了数万个数据的模拟试验。如：最佳足长、肩宽、肌肉的成分与结构、动态视力等等，最后查明了究竟什么样的人种的遗传基因特性才能满足上述条件。

这种理想的遗传基因组合在资料情报中心终于凑齐了。

在符合“运动遗传基因保护法”的前提下，政府决定立即对其进行人工授精，然后由指定的女子来孕育、生产。

从那之后，我就在国家的设施中长大。至今，我摄取营养、排泄、生活周期等一切都在计算机的控制之下进行。

我是根据国家的体育政策而诞生的超级运动员，在短跑方面是完美无缺的。

我体能的高峰期与下次奥运会的举办时间正好相符。

当然，像前文所述的那样诞生长大的人并不仅仅我一人，本次奥运会就有许多这样的选手参加。如：身高三米的篮球运动员、体重三百公斤的无差别级摔跤运动员，或者脚像鱼鳍那样巨大而扁平的游泳运动员等。他们都像我一样，是通过遗传基因计算而培育出的试管婴儿。在奥运村，常常会因与形态怪异的人相遇而大吃一惊。奥运会眼看就要变成超人大会了。

然而，在这类运动员当中，有一个人却格外引人注目。

他的打扮很怪异：全身裹着黑披巾，头上也蒙着头巾，只露出两只眼睛。

他经常与一个教练似的人在一起，从不到食堂与大家共同进餐，或是开开玩笑聊聊天什么的。我在走廊或院子里不时见到他，但令人不解的是：他总是扶住教练的肩膀，摇摇晃晃地走路。

据说他是东亚一个小国的短跑运动员，可奇怪的是，他从未到过训练场。我想：难道他得了连路都不能走的重病吗？倘若如此，为什么不去医院，而悠闲地待在奥运村里呢？

有一次，我终于忍不住问他：“您的腿是不是有什么病？”

“不是……”他的教练微笑着答道，“请您别太在意。因为他是克隆人，所以身体的形态有点变化。”

他自己什么也没说，只是用那黑色头巾下闪光的眼睛瞥了我一眼。

身体的形态？

确实，克隆人有由于遗传基因的组合不同而身体发生异常变化的人，并且能在比赛中大显身手。比如：有的游泳运动员在水中能够像鱼儿一样自由自在，上了陆地却不能站直。

不过，他和我一样是短跑运动员，可为什么是这副怪样子？仿佛连走路的功能都要失去的身体，能跑得快吗？而且，他还把全身都遮掩起来……他究竟是什么种族的后代呢？

解开疑团的机会终于来了。

那是百米跑预选赛。我和他编在同一组，并且跑道紧挨着。他与往常一样，被教练搀扶着摇摇晃晃地来到起跑线，摆好了起跑姿势。

发令枪响了。

观众们顿时沸腾起来。我竭尽全力地奔跑，尚不知道沸腾的原因。可是不久，他的身影突然出现在我的斜前方。

多么惊人的速度！一眨眼，我就被远远地甩在后面。

咦？他正像动物似的手足并用地奔跑着！

简直不敢相信自己的眼睛，我的大脑也仿佛麻木了。这时，我突然发现他的运动裤后面有什么东西露了出来。

是条尾巴！


# 那些你所不知道的大事

作者：李月亮

在你的生命里，经历了一些很重大的事情，可是你并不知道。

5 岁那年，爸爸下班回来，你跑去迎接他，不小心摔了个狗啃泥，不过没有受伤。

你并不知道，就在你摔倒的地方往左两厘米，立着一根小钉子，如果你稍微偏一偏，左眼就失明了。

10 岁那年，你一个人在家煮方便面，刚把水壶放到煤气炉上，就接到妈妈的电话让你去姥姥家，你完全忘了开着的煤气炉，锁上门就走了。多么幸运，当壶里的水被烧干了，煤气正好用完了。一场势不可挡的火灾没有发生。

15 岁那年，某天晚上，你下了晚自习，像往常那样回家，你肯定没有想到，在刚刚经过的那条小路上，几个小流氓欲拦住你图谋不轨，可是刚好一对夫妻走了过来，坏蛋们一胆怯，放过了你。

25 岁那年，你怀着孕，不小心感冒了，去医院打针时粗心的大夫开错了药。当护士拿着会致胎儿畸形的甲硝唑准备给你打时，路过的护士无意间看了一眼，刚走过去又折回来，悄悄提醒那个护士说，孕妇不能用这个药啊。谁也不知道，如果那天药打进去，会是什么结果，反正你是幸运地躲过了厄运。

有那么多次，你都差点掉进悲伤的深渊，可是，你幸运地躲过去了。不得不说，有那么多时候，上苍都眷顾着你，救你于苦海。

如果知道了这些，你还会为了一点小困难小失败小痛苦去埋怨吗？考试的低分，恋人的背叛，身体的伤病……相对那些躲过去的灾难，这些算得了什么？所以，亲爱的，在困难的时候要相信，其实生活对你很眷顾。

当然，在你的生命里，还有一些大事情，你并不知道。

6 岁那年，爸爸准备送你去少年宫学习绘画，可是，由于奶奶生病，那个暑假他们没有时间接送你，就把这件事放下了。没有人知道，如果当时得到专业的培训，以你的天赋，就会在这方面取得不凡的成就。

18 岁那年，你暗恋已久的男生准备向你表白，信已经写好了，又专门跑到你家楼下小心翼翼地投进信箱。可是他记错了楼号，那封信，被邻居拿到，疑惑了好久之后，给丢掉了。一个男孩，一段青春里最美好的恋情，就这样与你擦肩而过。

24 岁那年，你到一家非常好的单位求职，费尽心思终于闯到最后一关，却还是失败了。你并不知道，其实本来你的名字已经在录取的名单里面了，可是，在敲定人选的会议上，一位重量级的评委把你记成另一个表现很差的人，坚定地投了反对票。就这样，别人一个莫名的小失误，让你失去了一份梦寐以求的好工作。

这样的事情，大概还有不少。有那么多次，命运本来已经要改变了，却在最后的关头，因为莫名其妙的偏差，掉转了方向。哦，或许，你的运气实在不怎么样。

所以，亲爱的，当你的彩票中了奖，当你的古董升了值，当你顺利地考上大学又考上了研究生，当你成为单位里最年轻的管理者……不要让自己飘起来，不要轻易地以为自己的运气和实力多么好，要知道，这只是你人生里本来可以发生的美好事情的一部分——还有一部分，你并没有得到。

真的，生活并不完全是你看到的样子，很多大事情你经历了却并不知道。如果你知道了这些，你大概就不会对现在的得与失太在意了。

没错，每个人都不是步步摔跟头的倒霉蛋，更没有人是一帆风顺的命运的宠儿。

看淡那些事情，平静而踏实地经历生活的起落，相信你会生活得更好。


# 穿过大半个中国去睡你

作者：余秀华

其实，睡你和被你睡是差不多的，无非是

两具肉体碰撞的力，无非是这力催开的花朵

无非是这花朵虚拟出的春天让我们误以为生命被重新打开

大半个中国，什么都在发生：火山在喷，河流在枯

一些不被关心的政治犯和流民

一路在枪口的麋鹿和丹顶鹤

我是穿过枪林弹雨去睡你

我是把无数的黑夜摁进一个黎明去睡你

我是无数个我奔跑成一个我去睡你

当然我也会被一些蝴蝶带入歧途

把一些赞美当成春天

把一个和横店类似的村庄当成故乡

而它们

都是我去睡你必不可少的理由


# 我觉得自己会永远生猛下去

作者：王小波

我过二十一岁生日那天，正在河边放牛。下午我躺在草地上睡着了。我睡去时，身上盖了几片芭蕉叶子，醒来时身上已经一无所有（叶子可能被牛吃了）。亚热带旱季的阳光把我晒得浑身赤红，痛痒难当，我的小和尚直翘翘地指向天空，尺寸空前。这就是我过生日时的情形。

我醒来时觉得阳光耀眼，天蓝得吓人，身上落了一层细细的尘土，好像一层爽身粉。我一生经历的无数次勃起，都不及那一次雄浑有力，大概是因为在极荒僻的地方，四野无人。

我爬起来看牛，发现它们都卧在远处的河岔里静静地嚼草。那时节万籁无声，田野上刮着白色的风。河岸上有几对寨子里的牛在斗架，斗得眼珠通红，口角流涎。这种牛阴囊紧缩，阳具挺直。我们的牛不干这种事。任凭别人上门挑衅，我们的牛依旧安卧不动。为了防止斗架伤身，影响春耕，我们把它们都阉了。

每次阉牛我都在场。对于一般的公牛，只用刀割去即可。但是对于格外生性者，就须采取锤骟术，也就是割开阴囊，掏出睾丸，一木锤砸个稀烂。从此后受术者只知道吃草干活，别的什么都不知道，连杀都不用捆。掌锤的队长毫不怀疑这种手术施之于人类也能得到同等的效力，每回他都对我们呐喊：你们这些生牛蛋子，就欠砸上一锤才能老实！按他的逻辑，我身上这个通红通红，直不愣登，长约一尺的东西就是罪恶的化身。当然，我对此有不同的意见，在我看来，这东西无比重要，就如我之存在本身。

天色微微向晚，天上飘着懒洋洋的云彩。下半截沉在黑暗里，上半截仍浮在阳光中。那一天我二十一岁，在我一生的黄金时代。我有好多奢望。我想爱，想吃，还想在一瞬间变成天上半明半暗的云。后来我才知道，生活就是个缓慢受锤的过程，人一天天老下去，奢望也一天天消失，最后变得像挨了锤的牛一样。可是我过二十一岁生日时没有预见到这一点。我觉得自己会永远生猛下去，什么也锤不了我。


# 长篇


# 早餐

作者：纪大伟

当妻子和儿子还在赖床的时候，身为人夫、人父的他就在厨房忙了。他不但在家吃早餐，而且负责张罗早餐。

他在餐桌上摆妥食物，等候刚起床的妻儿姗姗就位。

妻和他都要上班，儿子要上学，一家三口都该吃饱早餐才能出门。以前他图方便，从外头带烧饼油条回家；后来，他觉得外带食物诚意不足，便改而在家亲手料理。

他每天专程回家做早餐──不过天亮之前的时辰，他并不在家里。他和无性多年的妻达成默契，放他在外过夜。当初他的别扭借口是：他必须熬夜加班，在办公室的便床假寐即可，何苦半夜三更回家吵醒神经衰弱的妻。。。。。。。。忧郁的妻不置一词。

自此，他便很少回家过夜。

当然，他不可能委身办公室──他另有情人的家可去。

他夜夜在情人床上痛快燃烧。但，他有个原则：欢爱之后，一定要及时赶回自己的家，自动自发准备早餐，藉此补偿妻儿。

唯有如此，深夜的放浪才可以和清晨的美德达至平衡。他提供早餐的丰盛程度，和夜里的欢愉指数形成正比；前一夜越销魂，翌日早餐就更动人。

他在夜里受惠，一定要以食物具体反馈寂寞的妻儿，否则罪恶感会咬人。

他犹记得情人的乳头，一转身便替妻端上草莓色拉；他一面回味情人的金黄色下腹，一面为儿煎了蜂蜜松饼。忙碌的早餐，营养的赎罪。

他再也没有在家过夜。他的妻儿却也没有缺过任何一顿良心的早餐。

但情人迭出怨言，因为他永远照规矩办事：云雨之后，他依例冲凉，回情人的床补睡几小时，在天亮之前警醒起身，随即驱车返家，毫不失误。情人想要留他共进早餐，但他总不肯。情人叹道，这不公平。

他却觉得公平极了。他的下半身、一天的下半段分给情人；

他的上半身、一天的上半截就该保留给妻儿。情人不该上下通吃，太贪心了，会害他失去平衡。

情人节那一夜，情人再次哀求他在翌日留下吃早餐。

他暴烈不耐，失手掴了情人一掌。未料，这一掌反而掀起欲望的海啸，两人欲仙欲死。狂战数回之后，他睡得不省人事，忘了冲凉。

他甚至睡过头了──竟是刺眼的阳光将他扎醒。他跳下外遇的床，气极败坏质问情人：为何不叫他早起？他赶不及回家做早餐了──早餐？都已经过中午了，等着吃午餐吧。

情人娴静煎着两人份的牛排。而他拂袖而去。

他沮丧回家，一路塞车。中午十二点半。他卡在十字路口，一边是上班之路，另一边是回家的方向。下午一点半。他心生不祥预感，无意上班，只想回家查看。他的生殖器官对不起妻儿的消化系统。

他进了家门，诧异家里竟然阴暗窒闷──他记得马路上又热又亮的空气。

他摸索打开饭厅的灯，看见妻子一身鼠灰套装，儿子穿妥整齐制服而且紧抱书包，妻儿两人坐在空无一物的餐桌前，彷彿有史以来这两人就坐在那里，从来未曾移动过。

他不解发生何事，只好问儿子（反正他不敢注视妻子的眼）："你和妈妈怎么没有去上班上学呢──现在已经下午两点半了……”

儿子盯着他，眼神酷似妻。“好饿，我们还没吃早餐。”

屋外骄阳高照，他家里却还没开始天亮。


# 波心

作者：亦舒

我认识周成辉的时候，不知道他家那么有钱。

我们在一个很偶然的场合遇到。我也并不是一般的所谓小家碧玉，我自己有房子有车子，有一分很丰厚的固定入息，银行也有一笔定期存款，生活的悠哉优哉，也就是社会上人称的高贵仕女。

我们在停车场里起了一点争执，不打不相识。

当时我的车角碰到他的车角，什么也没有损伤，但是他的女伴冲出来骂我。

我抬起头看她一眼，当她是个透明人物。

我心里这样想，如果她召警，我就跟警察说话，光是谩骂，我是不怕的。

结果是他把女伴拉进了车。

我并不记得他的车子，那只是辆很普通的汽车。

第二天在停车场有人向我微笑、抱歉，我丈八金刚摸不着头脑。

他提醒我。

我说“呵。”

“对不起。”

我说：“没关系，这种小事情随时可以发生。”

他当场赞我，“真是个大方的女子。”

我很讶异。这些小气小事算得什么？除了骄纵成疾或是神经病之外，谁都不会放在心中。

我不再与他勾搭，一个人上路回家。

但接连好几天都在停车场遇见他。我想我们办公的地方很近。

我一直假装看不见他，不去注意他。

半个月之后的一个星期五，下班后下雨，工作上又受了些真正的气事，我没有直接回家，到附近酒馆去喝了两杯，才去取车。

风一吹，酒气上涌，很有点感慨，坐在车中发怔。

有人同我说：“你不舒服？”

我才起头，又是他。

他伸出手，“我叫我周成辉。”

我向他点点头，他有很诚恳的笑容。

“我们认识已经很久了，你不介意把名字告诉我？”

我说：“我是莫纫玉。”

我们握握手。

并没有介绍人，所以我也不知道他的底细。

我们这样子便成了朋友，有时候下班一起去吃饭，周末他也来约我看场戏。

当时我没有其他的男朋友。

我这个人不喜欢与男同事走，上班八九小时对着已经很累，下班还是那些人，惨过结婚。

公司里人多声杂，七嘴八舌，啥子秘密都没有，我不会做这种傻事。

工作忙，生活圈子窄，日子久了，也根本没时间去结识别的人，生活可以说是相当枯燥，但是我并不想胡滥结交男朋友。

周成辉刚刚好，一星期界一、两次面，作为调剂，非常愉快，适合我的生活节奏。

我们的节目与普通男女的节目一样，很平凡，他没有送我重礼，也没有邀请我参加盛大的舞会，我一直不晓得他的父亲就是鼎鼎大名的周某人。

我当时只晓得他有一份不错的工作，未婚，为人沉静，有幽默感。

直到 1 年后，我们感情有点基础之后，他请我到他家吃饭，我才发觉这件事。

他亲自接我，我穿得很普通，但为了见别人的父母，选比较庄重的款式，带了唯一的珍珠项链。

成辉在打量我，他表示很满意，我们便出发。

车子一直向郊外驶去，我就知道他父母比我想象中要有地位得多。

当车子停在那栋著名的中式别墅前面时，我略为惊讶，但不失大方地说：“这里？”这个时候，如果不表示一点错愕，就显得做作。

屋子里的美仑美奂，华贵沉着，一派世家的气度。当晚约请了五十位客人，成辉一一替我介绍，我恰如其分地应付，因有他在我旁边，并不觉得特别累。

晚宴完毕，他又送我回家。在途中我说：“你没有早告诉我。”

他答得好：“这种事很难开口，你叫我怎么说，伸出手来道：‘我父亲是有财有势的周某某’？”

我微笑。这倒是真的，真那么说话，我第一个吃不消，谁耐烦他的父亲是谁？

“你当没有被宠坏。”我说。

“我父母家教很严。”

“有钱人家的子弟很少被他们的父母宠坏，多数为社会上势力的眼光宠坏才真。”

“说得有理。”

“我不会因你父母有钱而对你持任何偏见。”

“谢谢你。”他由衷地说。

倘若要人不知，除非己莫为，消息还是传开了。

有女同事向我打听，“你男朋友是周某的公子？”

“我没有男朋友。”我微笑。

“明明有位周君。”

“那只是普通的朋友。”

“是不是公子？”

“弄错了，他是个小职员，薪水跟我们差不多，就在隔壁爱高洋行任营业经理，这真是误会，是怎么传开来的？说来听听。”

同事被我弄得没法子。

我仍然跟周君约会着。我说得出做得到，真的对他与以前一点分别都没有。

我不知道他心中怎么想，我则觉得事情跟以前是不一样，以前我认为我们还可以有进一步的发展，现在？

如果我是个一无所有的女人，我的想法又不一样，反正什么都没有，无牵无挂，不如孤注一掷，嫁入豪门，可以扬眉吐气，即使败则为寇，也没有损失。

但我有我的社会地位：正当的家庭出身，持有大学文凭，一分高薪的职业，豪门并不是我梦寐以求的归宿。

我有我自己的宗旨，理想，目标，我的性格已经成型，自己才是真正可贵的。

要在这个小城里出风头，也不一定要进入豪门才行，另有许多旁门左道与康庄大道。

私底下，我已有疏远周成辉的打算。

我当然没有自己说得那么天真大方。

切忌吃不到羊肉一身骚。谁没有坐过劳斯莱斯丹姆拉，光坐有什么用，要连司机保养费车房一起送过来才好，看样子周成辉并没有资格供给这一切，所以不能为他牺牲太多。

成辉有习惯送花给我。通常是白色的，香喷喷的花。

我很期望这些花束的来临，时常想，如果真的不同他来往，多么可惜这些花也会跟着失踪。

没想到过了一个月，成辉说：“我父母想见你。”

钻进我脑袋的第一的念头便是：这是面试。

但是我并不想考进这个大家庭担任什么职位。

我说：“我最近比较忙，也许公司会调我出差。”

他一怔。“咦，很平常的社交，为什么推托？”

“我……不想见他们。”我终于说老实话。

“为什么？”他问：“你已经见过他们一次。”

“但那次有五十个人。”

“不错。所以这次想与你多谈谈。”

“不必了。我这个人乏善足陈。况且我们又不是深交。”我说得很明白，“你同我推了他们。”

“纫玉。我不明白你。”他很困惑。

“我总有种感觉，‘见伯母’是很严重的发展。”

“可以这么说，所以你不得不去。”

“你在暗示什么？”我问。

“我想公开你是我的女朋友。”

我微笑，这一招可瞒不过我。将来有什么变化，难道我还登门向他父母算帐不成？这也是收买女人信心的一种办法。

可是我在社会上泡得实在太久了。见识广得很，我仍然摇头。

我说：“做朋友是做朋友，不必公开。”

“假如你们在街上碰见，都不认得，那有什么好？”周君很不以为然。

“周老先生太太大概坐着轿车里的时间居多，不会轻易碰到不相干的人。”

他凝视我，我也微笑着看他。太可惜，我们第一次有了不同的意见。

“你为什么那么小心？”他看出来。

“我是个出名自爱的人。你看，每个人都得为他的行为负责，做过什么，便是墨迹，但在生命的白壁上，人人看得见。不介意世人说什么，但是我自己觉得碍眼，就不大好。”

“我想我有点明白你说些什么。”他问：“我是墨渍？”

“当然不是，你是我朋友。但见过你父母，又没进一步的发展，落了把柄，就是墨渍子，何苦呢。”

“天呀，你太谨慎了，假如他们不是他们，你还会不会去见他们？”

“我也不会。”我说：“我对伯父伯母一向没有兴趣。”

“你的意思是，除非我娶你……”

“嘘，我从来没有这么说过，周君，你千万别误会，我暂时绝无想到婚姻，你要慎于言。”我很肃穆地说。

“对不起。”他说。

“我应该说对不起才真。”

“父母会失望。”

“我相信不会，”我越来越客气，“他们可见的要人多得很。”我赔着笑。

周君见不得要领，便闷闷不乐的告辞。

他大约觉得父母肯接见我，是我的荣幸吧。但是我日出而作，日落而息，帝力于我何犹哉。

我不是没有烦恼，本来我想换一部比较好的车子，世人都知道最扎实最保值的车子便是平治，但现在换车，全公司以为我一搭上公子哥，连坐驾都升一级，那还了得，我岂不是太冤枉。

于是我仍然开着我的日本车。

周君说得对，我是很小心。

我才二十七岁，人的悲剧是永远有可能活到八十岁。我乐得好好养生。

周君说他不明白我，“你又没有其他男朋友……”

我微笑。

“你不原谅我是他们的儿子？”他又问。

“我根本不关心你是谁的儿子。”

他搔搔头皮，“你真是个特别的名字，你仿佛似在冰箱里走出来似的，冷冰冰。”

我说：“外头有很多热情如火的女子等待着要结识有钱的公子，你到随便哪一间的迪斯科去晃一晃，保证有三车抛媚眼轻骨头跟着你回家。”

“我不是那样的人。”他对我说着笑出来。

我说：“这是我们还可以做朋友的原因。”

他又不得要领。

做人不是那么容易的，真正能帮你扬眉吐气的人是你自己，没有别人。就是这么简单。

此后周君建议的跳舞乘船节目我都一一地推了，他觉得兴致索然。

我什么都不鼓励他，但还是身不由主的结识了他的父母。

在我们公司的酒会，总经理为我介绍周家两位老人家，我很客气的点头，当作是第一次相会，怕他们早已忘记我是谁。

谁知道周太太眯眯眼说：“这位莫小姐是小儿的密友，我怎么会不知道。”

我呆住。

总经理也呆住。

我尴尬得巴不得找地缝钻。

周太太拉住我的手，“怎么不到我们家来？我约你都有不到，公事忙是不是，刘经理，我当你面前向你讨个人情，别忙坏了她。”

我忙说：“不不不！”

总经理立刻赔笑，“她事业心是重一点。”

周太太笑说：“我不反对女孩子做事，可是……”

总经理认为：“要不要放两天假？”

“好，”周太太代我答：“那么我们约明天下午，喏，你不准推了。”

我瞠目结舌，无端白事的得了两天假，接了一个约会。

后来总经理笑着对我说：“婚姻是人生大事，你也太拘谨了，人家父母都承认下来，你还不肯告诉人，最难过的一关便是老人家，他们选媳妇，不得不小心。”

我不知说什么才好。

我不知道周君原来这么认真。

嗳，我还以为他是唬我的呢。

第二日赴约，成辉来接我。

他说：“姜是老的辣，由他们出马，你到底答应了。”

我有点歉意，不出声。

周先生与周太太很客气，一早在家等我。

我们闲谈了几十分钟，他们很想知道我的家庭状况，我照实说了。

“父母去世，留了点小资产给我，有一个哥哥，在美国加州州立大学做教授，机械科，是，结了婚，有四个孩子。……今年二十七岁了，不知怎么搅的，大学毕业已是二十三，不过做了四年事。升得快？大家都这么说。”

看得出他们对我相当满意。

周先生问得很露骨：“你喜欢大家庭还是小家庭？成辉的三个兄嫂全部在这里住。”

我很坦白：“我爱小家庭。”

成辉怪我太坦率，眼睛朝我看来。

我说下去，“妯娌很难相处得好，我与老人家的生活习惯也有所不同。”

周太太问：“不可以迁就吗？”

我微笑不语。

还是十八九岁的少女比较适合他们。

“这里一切都现成：佣人，车子，房子……怎么样，不喜欢？”周太太当我如一个孩子。

我不语，我家里的一切何尝不是现成，也并不是太差呢。

“女孩子长年累月地做事，很吃苦的。”周太太又说。

“真的，”我赞同，“很吃苦。不争呢，变得无能，一争，便成泼妇。”

成辉说：“不如嫁人算了。”

他母亲也笑说：“我们家媳妇都不必做事。”

“是吗？”我问：“是否每个月收月规钱？否则零用怎么办？”

周太太说：“我们家人身边哪用拿现款，一切签信用卡，待爹爹付钱好了。”

“什么？”我觉得十分荒谬。

“怎么，不习惯？”

我说：“我是习惯靠一双手的。”我笑，“做出瘾来了。”

周老先生说：“真是个有志气的好女子。”

我说：“不算得了，我认识许多人赚了钱自己读大学的。”

周太太说：“成辉，你真该学学这种毅力。”

成辉总是笑。

我说：“他很好，并不是一般传说中的公子哥儿那种德性，他很发奋做事。”

成辉耸耸肩。

这顿饭吃得很轻松。

我并没有发表太多的伟论。

成辉把我送回家的时候说：“他们很喜欢你，说你是完全不同的一个人。”

“跟谁不同？”我问：“你以前的女朋友？”我想起在停车场冲出来与我交涉的那个女子。

“跟我三个嫂子。”

“她们都很出名美丽。”

一个是电影明星，另两个是名门之女。

成辉说：“她们也很好，不过你跟她们不同。”

“我的主张特别多。”我笑。

“他们并不介意。”

我很介意，有一个女朋友嫁入豪门，光是过节时办礼物就穷三代，还得代娘家张罗了送到夫家去，一年不知多少人生日，烦都烦死。

我笑一笑。

“你光是笑有什么用？”成辉有点生气。

“这是无可奈何的笑。”

“你的理想夫家是怎么样的？”成辉问。

“门当户对，老人家有点节蓄，住得很宽裕，有两个佣人够了，爱孩子，”我不假思索地说下去：“可以照顾我们，但不必太有钱。”

成辉说：“我父母觉得你最可爱的地方便是嫌他们钱多。”

我笑出来。

“每个媳妇都可以得到三套首饰，完全属于她们自己，戴完不必归还保险箱。”成辉说。

我温和地说：“有什么是不必付出代价的呢？连人都锁进笼子里，何需担心保险箱？”

成辉无奈，“嫂子她们穿衣服都是一流的，拿信用卡去名店签个字就可以无限度地买，爸妈喜欢媳妇穿得好。”

“我穿得不好吗？我也是件件名牌呀，”我说：“嫁人后烦恼也多得不得了。”

“从来没见过像你这样乐天知命的人。”成辉说：“我服贴了。”

每样事要付出代价，真的，我已经在付。

在公司里，总经理对我客气得不得了，大概认为我快要成为周家的媳妇，轻易不肯得罪我，一传十，十传百，大伙儿都对我刮目相看。

因为我不是胡乱在外承认谁谁谁是我男朋友，是周老先生及夫人亲口说的，身分又不同。

事到如今，别的男人也不来约会我了。

过一两日，成辉说：“爸爸说，要搬出来住不大好，怕其他的嫂子要有样学样。”

“你要搬出来往？”我故意装佯。

“纫玉！”

“为什么你要独自搬出来住？”

“你正经点好不好？”成辉问。

“十划还没有一撇的话。说来作什么？

“跟大人住是有好处的。”他说：“方便。”

我只笑不语。

不是我。我不需要大人照顾。大人七点半起床，我也要七点半起床，大人十二点正吃午饭，我吃不下也要吃。大人肩着的老佣人，动不动给新媳妇看面色。

不不不。

“我真是说不服你？”

“成辉，你又何苦要说服我？”

“我已深深爱上你。”

“呵？什么时候发生的事？”我讶异，”我以为咱们是君子之交。”爱，真是的。

“气死我。”他摇摇头。

我温和地说：“气死你我才不想，谁送玉簪花给我呢？”

他也微笑，“你还要与我斗到几时？”

我不肯答。

“我知道你是个顶顶聪明伶俐的女孩子，可是这么功心计，又是为了什么？”

我假装没听见。

“我不会亏待你的，纫玉，你何必担心？”

我翻阅杂志，索性装到底。

“一定要搬出来住，一定要让你工作，还有什么？当然，不得逼你做生孩子机器，是不是？”

我抬起头来，即使是有了这些自由，我的牺牲也还是很伟大的。三个嫂子！当然，都是落落大方，礼貌客气有教养的女人――一如果你是她们普通朋友的话。做了亲戚，恐怕就不是这样了，恐怕眉梢眉角就叫人受不了。

女人，我知道女人的通病，我自己是女人，我就有这些通病。

我不能不见她们，到底是亲戚。在一间公司里，新来报到尚且要受同事欺侮，别说是大家庭，除非总经理；老爷奶奶特别赏识我，但我又有自知之明，我不会吹捧拍马。时间一久，新鲜一过，恐怕不大受欢迎。

况且他们周家怎么会让媳妇抛头露面地出来做事？

要做也可以，装模作样开家精品店，叫媳妇去看看橱窗设计，到巴黎出差做买办之类，弄得不好，关了门从头来过，三十年也创不出事业来。

到时身体懒了，朋友全部疏远，也只得听他们摆布。

我叹口气。

看到成辉迫切盼望的样子，我不是不心动；但蜀道实在难走。

要我扔下现在的一切，去走条不知名的路，实在难以取舍。假如在刚刚毕业的时间遇见他，又还好些。

这样拖下去，过不了很久，成辉就会转头舍我而去。多么好的机会，放弃可惜，他为人正直刚毅，有很多优点，以后未必碰得见这么好的男人。但若果不论争取的嫁蛤他，将来一定后悔。

我怎么也不会习惯同老爷奶奶，六个兄嫂，四个女佣，两个男工，两个司机，以及四个孩子一起住，老天处老天。连丈夫在内，二十二个人！

“纫玉，说话呀。”

“我无话可说。”相对无言。

不但他烦、我自己也觉得烦。

上下班除外，多余的时间我给这件事搅得很累。回到家什么都不想做，变得很内向。

约会又疏落起来，当花柬不再到达的时候，我已明白发生了什么事。

如果我会嫁入周家成为他们的附属品，他们会考虑，要成辉出来与我一起奋斗，过新生活，那是没有可能的事，成辉也没有这个勇气。

物以类聚。我们冷了下来，这样过了一个月。

一日上班，发觉同事们头碰头在议论纷纷，一见到我。立时静止。

这分明是在说我。

我有什么值得被人说的地方？

还不是周成辉。发生什么事是我不知道的？

终于有人忍不住，拿了一本秘闻周刊来放在我桌子上，何：“这是真的吗？”

我低失一看，大字标题：“林美娟嫁周成辉”。

我问：“林美娟是谁？”

“宝岛歌后。”

“周成辉是谁？”

“你的男朋友呀！”

“我从来没有一个男朋友叫周成辉。”我笑，“你们弄错了。”我几时承认过。

“嗄？”只好出去。

我伏在桌子上。原来如此，长叹一声。

“我很有失落感，算算日子，相识至今，有八个月光景。人家说这段时间内最适宜结婚。诚然，但他并没有等我，我也没有迁就他，就这样告一段落。

我控制得很好，在写字楼胡混一日，下班到停车场，看见周成辉在那里等我，他是故意要见我。

“恭喜。”声间比我想象的还要平静。

“是爸妈的意思。”他说。

我点点头，什么借口都是一样的。

“我换了一家公司做事。”他说。

以后见不到面了。今天是最后一次。

“我们可以通电话。”

可以吗？还可以吗？真的？我又微笑了。

“再见。”我坐进车子内。

“再见。”他说。

萍水相逢，两人都太过吝啬，不肯付出感情。

于是事情过后，各散来西；城市人的感情，原应如此。

我是天上的一块云，偶年投影在你的波心。


# 老王

作者：杨绛

我常坐老王的三轮。他蹬，我坐，一路上我们说着闲话。

据老王自己讲：北京解放后，蹬三轮的都组织起来；那时候他“脑袋慢”，“没绕过来”，“晚了一步”，就“进不去了”。他感叹自己“人老了，没用了”。老王常有失群落伍的煌恐，因为他是单干户。他靠着活命的只是一辆破旧的三轮车；有个哥哥死了，有两个侄儿“没出息”，此外就没什么亲人。

老王不仅老，他只有一只眼，另一只是“田螺眼”，瞎的。乘客不愿坐他的车，怕他看不清，撞了什么。有人说，这老光棍大约年轻时候不老实，害了什么恶病，瞎掉一只眼。他那只好眼也有病，天黑了就看不见。有一次，他撞在电杆上，撞得半面肿胀，又青又紫。那时候我们在干校，我女儿说他是夜盲症，给他吃了大瓶的鱼肝油，晚上就看得见了。他也许是从小营养不良而瞎了一眼，也许是得了恶病，反正同是不幸，而后者该是更深的不幸。

有一天傍晚，我们夫妇散步，经过一个荒僻的小胡同，看见一个破破落落的大院，里面有几间塌败的小屋；老王正蹬着他那辆三轮进大院去。后来我坐着老王的车和他闲聊的时候，问起那里是不是他的家。他说，住那儿多年了。

有一年夏天，老王给我们楼下人家送冰，愿意给我们家带送，车费减半。我们当然不要他减半收费。每天清晨，老王抱着冰上三楼，代我们放入冰箱。他送的冰比他前任送的大一倍，冰价相等。胡同口蹬三轮的我们大多熟识，老王是其中最老实的。他从没看透我们是好欺负的主顾，他大概压根儿没想到这点。

“文化大革命”开始，默存不知怎么的一条腿走不得路了。我代他请了假，烦老王送他上医院。我自己不敢乘三轮，挤公共汽车到医院门口等待。老王帮我把默存扶下车，却坚决不肯拿钱。他说：“我送钱先生看病，不要钱。”我一定要给钱，他哑着嗓子悄悄问我：“你还有钱吗？”我笑说有钱，他拿了钱却还不大放心。

我们从干校回来，载客三轮都取缔了。老王只好把他那辆三轮改成运货的平板三轮。他并没有力气运送什么货物。幸亏有一位老先生愿把自己降格为“货”，让老王运送。

老王欣然在三轮平板的周围装上半寸高的边缘，好像有了这半寸边缘，乘客就围住了不会掉落。我问老王凭这位主顾，是否能维持生活。他说可以凑合。可是过些时老王病了，不知什么病，花钱吃了不知什么药，总不见好。开始几个月他还能扶病到我家来，以后只好托他同院的老李来代他传话了。

有一天，我在家听到打门，开门看见老王直僵僵地镶嵌在门框里。往常他坐在登三轮的座上，或抱着冰伛着身子进我家来，不显得那么高。也许他平时不那么瘦，也不那么直僵僵的。他面色死灰，两只眼上都结着一层翳，分不清哪一只瞎、哪一只不瞎。说得可笑些，他简直像棺材里倒出来的，就像我想象里的僵尸，骷髅上绷着一层枯黄的干皮，打上一棍就会散成一堆白骨。我吃惊说：“啊呀，老王，你好些了吗？”

他“嗯”了一声，直着脚往里走，对我伸出两手。他一手提着个瓶子，一手提着一包东西。

我忙去接。瓶子里是香油，包裹里是鸡蛋。我记不清是十个还是二十个，因为在我记忆里多得数不完。我也记不起他是怎么说的，反正意思很明白，那是他送我们的。

我强笑说：“老王，这么新鲜的大鸡蛋，都给我们吃？”

他只说：“我不吃。”

我谢了他的好香油，谢了他的大鸡蛋，然后转身进屋去。他赶忙上住我说：“我不是要钱。”

我也赶忙解释：“我知道，我知道——不过你既然来了，就免得托人捎了。”

他也许觉得我这话有理，站着等我。

我把他包鸡蛋的一方灰不灰、蓝不蓝的方格子破布叠好还他。他一手拿着布，一手攥着钱，滞笨地转过身子。我忙去给他开了门，站在楼梯口，看他直着脚一级一级下楼去，直担心他半楼梯摔倒。等到听不见脚步声，我回屋才感到抱歉，没请他坐坐喝口茶水。可是我害怕得糊涂了。那直僵僵的身体好像不能坐，稍一弯曲就会散成一堆骨头。我不能想象他是怎么回家的。

过了十多天，我碰见老王同院的老李。我问“老王怎么了？好些没有？”

“早埋了。”

“呀，他什么时候……”

“什么时候死的？就是到您那儿的第二天。”

他还讲老王身上缠了多少尺全新的白布——因为老王是回民，埋在什么沟里。我也不懂，没多问。

我回家看着还没动用的那瓶香油和没吃完的鸡蛋，一再追忆老王和我对答的话，捉摸他是否知道我领受他的谢意。我想他是知道的。但不知为什么，每想起老王，总觉得心上不安。因为吃了他的香油和鸡蛋？因为他来表示感谢，我却拿钱去侮辱他？都不是。几年过去了，我渐渐明白：那是一个幸运的人对一个不幸者的愧怍。


# 翻浆

作者：毕淑敏

那年，我从西藏回内地探家，需坐半个月的汽车。搭了一辆地方上运送旧轮胎的货车，从海拔 5000 米的高原俯冲而下，颠簸了 10 天，到了一处戈壁。正是春天，道路翻浆。

突然在无边的沉寂当中，立起一根土柱，遮挡了银色的车灯。

“你要找死吗？你！你个兔崽子！”司机破口大骂。

我这才看清是一个人。浑身是土的人。他穿着一件尿碱黄色的旧大衣，拎着一个生姜黄色的破袋子，袋口绑着一缕骆驼黄色的绳头。

“我不是找死。我要搭车。我得回家。”他每一句话中间都有很长的间歇，你以为他说完了，可是他又继续说下去。“不搭！你没长眼睛吗？司机楼子已经坐满了，哪有你的地方！”司机愤愤地说。

“我没想坐司机楼子。我蹲大厢板就行。”他的话语中渗出轻微的南方口音。司机还是说：“不带！这么冷的天，你蹲大厢板，会生生冻死！”说着，踩了油门，准备闪过他往前开。

那个土人抱住我们的车灯说：“就在那儿……我爱人生孩子了……没有奶……我到场部好不容易借到点小米……要是赶不回去，熬不出米汤，孩子就饿死了……我们的粮食早没了……”我说：“您的孩子是男孩还是女孩呢？”

“是女孩，好漂亮的！”他立即兴奋起来，笑容像干旱时地上的裂缝在他的脸上蔓延。

为了那个没有奶吃的女婴，我一咬牙说：“你上车吧。”

他立即抱着口袋往车大厢上爬，“谢谢谢……谢”最后一个“谢”字已是从轮胎缝隙里发出来的。

夜风在车窗外凄厉地鸣叫。司机说：“我有一个同事，是个很棒的老师傅。一天，他的车突然消失了。很长时间没有踪影，原来是个知青，化装成一个可怜的人，拦了师傅的车。

上车以后把师傅杀死，甩在沙漠上，自己把车开回了上海。直到案发，我们才知道真相。从此我们车队里的司机绝不搭任何不认识的人上车。你是我的老乡说了许多好话，我才破例答应的。”

我立刻心里一沉，我找到司机身后的一个小洞，屏住气向外窥探。

朦胧的月晕中，那个土色的男子如一团肮脏的雾，抱着头，龟缩在起伏的轮胎阵里，每一次颠簸，他都像遗弃的篮球，被橡胶击打得嘭嘭作响。

“他好像有点冷。别的就看不出什么了。”我说。

“再仔细瞅瞅。我好像觉得他要干什么。”

这一次，我看到搭车人敏捷地跳到两个大轮胎之间，手脚麻利地搬动着我的提包。那里装着我带给父母的全部礼物。“哎呀，他偷我东西呢！”

司机很冷静地说：“怎么样？我说得不错吧。”“然后会怎么样呢？”我带着哭音说。

“你也别太难过了。我有个法子试一试。”只见他狠踩油门，车就像被横刺了一刀的烈马，疯狂地弹射出去。车速接近极限。从小洞向外窥探，那人仿佛被冻僵了，弓着腰抱着头，石像般凝立着，企图凭借冰冷的橡胶御寒，我的提包虽已被挪了地方，但依旧完整。

我把所见同司机讲了，他笑了，说：“这就对了，他偷了东西，原本是要跳车的，现在车速这么快，他若跳下就是找死。他不敢动了。”

路面变得汹涌澎湃，车速减慢了。

我不知如何是好，回头去看那个窟窿。大厢上的人也很灵敏地觉察了速度的变化，不失时机地站起身，重新搬动了我的提包。

我痛苦地几乎大叫，就在这时，司机趁着车的趔趄，索性加大了摇晃的频率，就势猛地一歪，车身剧烈倾斜，车窗几乎吻到路旁的沙砾。

再看那人，他仆倒在地，像一团被人践踏的麦草，虚弱但仍不失张牙舞爪的姿势，贪婪地护卫着我的提包——他的猎物。

司机继续做着一整套的高难动作。我又去看那个人，他像夏日里一条疲倦的狗，无助地躺在了轮胎中央。

道路阴险地毫无先兆地平滑起来，翻浆也像被施了符咒，消失得无影无踪。司机说：

“扶好你的脑袋。”

我一时没明白过来是怎么一回事儿，但司机凶狠的眼神启发了我。就在他的右脚残忍地踩下去的前一秒，我醍醐灌顶，大彻大悟。剩余的时间只够我在明白了他的策略之后，采取最紧急的自救措施：双腿紧紧抵地，双腕死撑面前的铁板，整个身体绷得如原始森林里最古老最强韧的硬木……

不用看我也知道，那个大厢板上的男人，在这突如其来的急刹车面前，几乎被卸成零件。“怎么样？最低他也是个脑震荡。看他还有没有劲头偷别人的东西？”司机踌躇满志地说。

我想到贼娃子一举伤了元气，一时半会儿可能不会再打我的提包的主意了，心里安宁了许多。

那个男人艰难地在轮胎缝里爬，不时还用手抹一下脸，把一种我看不清颜色的液体弹开……他把我的提包紧紧地抱在怀里，往手上哈着气，摆弄着拉锁上的提梁。

那边，他扎在小米口袋上的骆驼黄的绳子，已经解开，就等着把我提包里的东西搬过去呢……

“师傅，他……他还在偷，就要把我的东西拿走了……”我惊恐万状地说。“是吗？”

师傅这次反倒不慌不忙，嘴角甚至显出隐隐的笑意。

“到了。”司机干巴巴地说。到了兵站了。这是我们今天晚上的宿营地，也是离那个贼娃子住的村最近的公路。他家那儿是根本不通车的，还要往沙漠腹地里走 10 公里……司机打亮了驾驶室里的大灯，说：“现在不会出什么事了。”

那个人挽着他的黄口袋，像个木偶似的往下爬，狼狈地踩着轱辘跌下来，跪坐在地上。

不过个把时辰，他苍老得分辨不出年龄了。除了原有的赭黄之外，脸上平添了青光，额上还有蜿蜒的血迹。

“学学啦……学学……”他的舌头冻僵了，把“谢”说成“学”。

我们微笑地看着他，不停地点头。

他说：“学学你们把车开得这样快，我知道你们是为我在赶路，怕我的小女儿喝不上米汤，现在到天亮前，我赶得到家了……学学……”他抹一把下颌，擦掉的不知是眼泪、鼻涕还是血。

司机一字一顿地说：“甭啰嗦了。拿好你的东西，回家吧！”

他点点头，恋恋不舍地离开了我们。

看着他蹒跚的身影，我不由自主地喝了一声：“你停下！”

“我要查查我的东西少了没有。”我很严正地对他说。

司机赞许地冲我眨眨眼睛。

那个土黄色的人孤独地面对我们，脖子柔软地耷拉下来，不堪重负的样子。我爬上大厢板，动作是从未有过的敏捷。我看到了我的提包，它像一个胖胖的婴儿，安适地躺在黝黑的轮胎之中。我不放心地摸索着它，每一环拉锁都像小兽的牙齿般细密结实。

突然触到鬃毛样的粗糙，我意识到这正是搭车人那截失踪了的绳头。它把我的提包牢牢地固定在大厢的木条上，像焊住一般结实。

我的心凌空遭遇寒流，冻得皱缩起来。

我的提包原是用一根旧绷带捆在车上的。经过长途跋涉，绷带磨断了，汽车的每一次急转弯，都可能把我给父母的礼物甩给大漠，搭车人发现了这个隐患，他解下了自己扎米口袋的绳子，想把我的提包重新固定……在寒冷与颠簸之中，他操作了一路……


# 小猫

作者：苏童

他们家是一座孕儿生产作坊。从六十年代到七十年代初，那个嗓音宏亮丰乳宽臀的女人让邻居们刮目相看。她在家门口倚墙而立时，怀里总是橡塞了一个米袋，她的浑圆的双臂交叉着做成一个容器，里面盛着一个毛茸茸的婴儿。你或许已经注意到那些婴儿的脸颊泛出粉红的光彩，是那种健康而美丽的粉红色，有点近似于月季花花瓣外侧的颜色。

女人们都叫她蓬仙，蓬仙生下了九个孩子，她自己对别人说，生到最后她咳嗽一下孩子就会出来，这叫什么事呢？都是冯三害了我，有一次蓬仙对几个女邻居赌咒发誓说，冯三要是再逼我做那档事，我，我他妈的就把他阉了！说着蓬仙还亮出了一把新的锋利的剪刀，她一边晃着那把剪刀，一边咯咯笑着，女邻居都知道蓬仙是在开玩笑，她们猜想蓬仙骨子里也是喜欢那档事的。

鬼才相信蓬仙那番话呢。蓬仙的衣裳又扣不住了，过了几个月，有人看见蓬仙又在剪尿布、手里抓着的正是那把缠了红线的剪刀。又过了几个月，蓬仙怀里的米袋看上去要掉下来了，又过了几天，冯家的第九个婴儿来到了我们的世界，没怎么就来了，只是啼哭了几声。

是个女孩，冯家人都叫她小猫。

冯家夫妇商量好了把小猫送给别人家当女儿。东门小学的老秦家无子嗣，又跟冯三沾亲带故的，蓬仙就在一大堆名单中挑选了老秦家，她说，那两口子不是老师吗？图他们是文化人，知书达礼的，孩子给了他们家，日后没准也能戴上个金丝眼镜呢，冯三挥挥手说，你说送谁就送谁，孩子一窝窝的都是你下的，我不管。

小猫生下来第三天老秦夫妇就来了，男的抱来一床棉胎，女的提着半包红糖，他们一来就被这个家庭吓着了，老秦抱着的棉胎被几个男孩撞落在地上。他刚要俯身去捡，从桌底下冲出两个女孩，争先恐后地跳到棉胎上蹦开了。老秦叫起来，别在上面蹦，这是新棉胎呀。冯三闻声出来，朝两个女孩头上一人扇了一巴掌，转脸对老秦说，到我家来不能带东西，什么好东西部让他们糟蹋了。老秦说，棉胎带来包孩子的，那包红糖是送给嫂子补身子的。冯三瞟了眼女人手里的半包红糖，有点鄙夷地说，没用，这些东西到我家都没用，我们的孩子三九天光着身子也能出门，冻不死他们，红糖更没用，蓬仙她什么都不爱吃，就喝粥。

蓬仙坐在床上纳鞋底，老秦夫妇一进里屋她就把脸转向墙壁，蓬仙说，抱走吧，我不心疼，我转着身子，你们别让我看见就行。

老秦夫妇绕着婴儿的摇篮转了几圈，夫妇俩交换着眼色，不时地耳语几句，却不跟蓬仙说话。蓬仙就用鞋底往墙上笃笃敲了几下，她说，喂，你们葫芦里卖什么药？是我送孩子给你们，难道还要我来下跪求你们吗？

老秦慌乱之中把婴儿的摇蓝摇得吱吱地响，他说，嫂子，你别催我们，让我们再考虑考虑。

蓬仙对着墙嗤地一笑，说，考虑考虑？那能考虑出个孩子来吗？

老秦的女人脸上有点挂不住，她伸手摸了摸婴儿的胳膊，吞吞吐吐地说，这女孩儿怎么不如他们结实健康，瘦得像只小猫，哭起来也不响亮嘛。

蓬仙对着墙说，你说这话就像个三岁的孩子，小宝宝生下来才三天，她才喝了三天的奶，怎么能比得上哥哥姐姐呢？

老秦的女人又伸手按了一下婴儿鼻子，她说，这女孩的模样长得也不如哥哥姐姐周正，眼睛就不大，鼻梁也有点塌，女孩儿家鼻梁塌一点是常有的事，但眼睛吃亏不得。

这次蓬仙按捺不住了，她忽然从床上冲下来，抱起摇篮里的小猫放进她的被窝，她像赶鸭子一样朝老秦夫妇挥着手，嘴里嘘嘘地叫着，走吧，你们快走，我还以为你们有文化，你们的墨水都灌到膀胱里了？我的孩子，刚生下三天的小宝室，你婉她丑？你这样的女人要是能生孩子，那才是老天瞎了眼睛。

老秦的女人当场就捂住脸哭起来了，她捂住脸跑到门边，还是回敬了几句，你有什么了不起？你怎么知道是我不会生？你们这种人除了生孩子什么也不懂，你们不懂科学！

蓬仙坐在床上拍了拍受惊啼哭的婴儿，她的嘴角上浮起一抹冷笑，哼，怪到男人头上去了？蓬仙低声嘀咕道，科学？科学也不能让公鸡下蛋呀！

你知道蓬仙是那种脾气火爆口无遮拦的人，一般人斗嘴斗不过她。更何况老秦夫妇多少有些理亏。他们夫妇脸色煞白地跑到门外，冯三还在后面追着说，孩子抱不抱都行，别这么走呀，喝口水再走。老秦的女人果然回来了，她想带走那半包红糖，但那些红糖其实已经不存在了，冯家的几个孩子每人手里都抓着一把，每人嘴里都发出吧嗒吧嗒品味的响声，她看见两岁的男孩小狗坐在桌子底下，正舔着包红糖的那个破纸包。老秦的女人站在一旁朝那堆孩子巡视了一番，出来就对老秦说，冯家的孩子，哼，我一个也不想要。

小猫还在蓬仙的怀里，小猫要送人的消息却传出去了。街上有人在谈论冯家的事情，那些菩萨心肠的妇人看见冯家的孩子，眼睛里便泛出湿润的悲悯的光，他们追上了玩铁箍的小牛和小羊，争着去摸小羊的辫梢，去替小牛翻好肮脏的衣领。绍兴奶奶毕竟有点老糊涂了，她没弄清楚冯家要送掉哪一个女孩，抓住小羊的胳膊不肯松手，绍兴奶奶说，这么俊俏的女孩儿，女孩儿大了比男孩疼爹妈呀，蓬仙怎么舍得把你送走？绍兴奶奶从衣襟上抽出手帕抹着眼睛，六岁的女孩小羊却朝她狠狠翻了个白眼，小羊尖声说；谁说我要送走啦？老东西，你才会让你妈送走呢！

与蓬仙交好的几个妇人则相约一起去看那个可怜的女婴。她们看见那个被唤做小猫的女婴，真的像一只小猫一样躺在蓬仙的怀里，两只小手也像小猫的爪子似地抓挠着蓬仙硕大的乳房。蓬仙一边喂奶一边缠旧毛线，或者说篷仙在缠旧毛线时腾出了身子给小猫喂奶。

一个妇人替蓬仙绷起毛线说，喂着奶手也不肯闲着，你要累死自己呀？

蓬仙说，我要不把自己累死，这些孩子怎么长得大？

另一个妇人上前抢过小猫抱住，在她脸上亲着，嘴里忍不住含沙射影开了，她说，可怜的小东西，你还笑呢，你妈要把你送人了你还在笑，你怎么笑得出来呀？

蓬仙的眉头跳了跳，沉下脸说，你要是心疼你抱回家去。

第三个妇人说，羊圈大了好养羊，七个孩子九个孩子还不是一样养，蓬仙你怎么会舍得把她送人？

蓬仙说，站着说话不腰疼，你才生了几个？告诉你们你们也不懂，生孩子生到我这份上，男孩女孩，长壶嘴的没壶嘴的，个个都心疼，个个都不心疼。

妇人们一时哑口无言，都愕然地看着蓬仙。蓬仙的眼圈有点红，抓过一块尿布嗤啦嗤啦地擤了把鼻涕，突然又笑起来说，我也糊涂了，我一心要找个比我疼孩子的人家，那不是糊涂？天底下的父母疼的是自己的骨血，哪儿会有我找的那户人家？我还在想呢，我这九个孩子个个跟野孩子似的，就不能有个白白净净戴金丝边眼镜的？细想想也不对，女孩子家眼睛坏了才麻烦，日后嫁了人，要是大伯子小叔子什么的爬错了床，她也看不清楚，那不是白白吃大亏吗！

你知道蓬仙就是这种像黄梅雨季的女人，雨下得急，太阳也说出就出，那天也一样，几个妇人后来被蓬仙逗得蹲在地上笑，蓬仙却不笑，瞪着女婴的手怔了一会儿，没头没脑地说，我是可怜他们。

你知道我们街上的妇人们大多是爱管闲事的，她们不打算把自己的孩子送给别人，但她们开始热心地为小猫物色一户好人家，当然她们每个人都清楚蓬仙心目中的好人家是什么条件。有一天她们终于与化工厂的女会计碰了头，女会计与一个海军军官结婚十几年了，还没有孩子，丈夫远在南海疆域，没有谁比女会计更需要一个孩子，几个女人在化工厂一角与女会计嘁嘁咕咕说了半天，后来她们就把女会计领到蓬仙家里来了。

那天恰逢小猫满月，蓬仙煮了一锅红蛋，顺手蘸了点蔻汁点在小猫的前额上，而冯家的其他孩子脸上额上也都画得红红绿绿的，分成两排伏在桌上，他们正吸溜吸溜地享受着小猫的满月面。

蓬仙却不怎么理睬女会计，旁边的说客刚要兜出来意，就被蓬仙制止了。别说了，我知道你们干什么来了，蓬仙咬烂了一口面条塞进女婴的嘴里，她说，真滑稽，把我们家当卖人口的铺子啦？

女会计脸色立刻尴尬起来，好在说客与蓬仙厮混惯的，她凑到蓬仙耳边低声说了一番话，蓬仙终于窃窃一笑，又说了一番话，蓬仙就哈哈笑开了，一边笑一边还揉搓着胀奶的乳房。蓬仙不时地朝女会计瞥上一眼，眼光有时是猜忌的，有时却充满怜悯。

这女孩长得丑，鼻梁塌，眼睛也小。蓬仙突然说。

孩子都可爱，我觉得她一点也不丑。女会计说。

这女孩瘦得像只猫，以后不知道能不能长得大。蓬仙又说。

你说到哪儿去了？女会计笑着说，只要细心照料，孩子哪儿有长不大的道理？只要你放心给我，我保证这孩子以后白白胖胖的。

我放了一半心。蓬仙审视着女会计，沉默了一会儿，倏地钻到被窝里去，用被子蒙住头说，抱走吧，抱走吧，别让我看见我就不心疼。

旁边的说客朝女会计使了个眼色，女会计求婴心切，果然抱起婴儿的褪褓就走。小猫并没有哭，倒是四岁的小牛追上来拽女会计的衣角，嘴里尖叫着，你偷我们家的东西。女会计夺路而走，边走边说，不是偷的，是你妈送的。女会计疾步走出冯家门，蓬仙还是追了出来，蓬仙光着脚追出来，一迭声地喊着，奶，奶，奶呀！

什么奶？女会计回头一看，蓬仙满脸是泪，倚在门框上，双手紧紧地按着自己的乳房。

奶，奶，蓬仙抹了把眼泪说，你没有奶水，你怎么喂孩子呀？

那没问题，人工喂养，我早想好了，女会计抱紧了婴儿，她说，我买奶粉、奶糕，还有鲜牛奶，鲜果汁，不会饿着孩子的。

人工喂养怎么行？孩子长不出力气。蓬仙上前在小猫脸上亲了一口，然后她突然做出了一个奇怪的决定，我来喂奶，我每天抽空给小猫喂两次奶，蓬仙说，三袋奶粉也顶不了我的一碗奶汁，不喝我的奶小猫长不大的。

后来的纠葛其实就是由喂奶引起的。女会计当时勉强点头应承了蓬仙，但她只遵从了两天。她告诉别人，看看蓬仙给小猫喂奶的样子，她心里别扭极了。既然你把孩子送给我，就该让我来哺养孩子，女会计满腹牢骚地说，凭什么说她一滴奶顶过三袋奶粉？孩子给了我，我就是她的母亲了，为什么非要喝她的奶呢？

蓬仙等了两天，不见女会计和小猫的影子，人就有点失魂落魄的。她想把小猫饿死啊？蓬仙这么喊了一声就冲出家门。她先是走了半个城市找到女会计的家。那门上挂着铁锁，门前晾着一排用新纱布剪成的湿尿布，蓬仙摸了摸那些尿布，忍不住嘀咕道，懂个屁，新纱布哪有旧的好？女会计的邻居告诉蓬仙说，陈会计还没下班呢，她刚过继了弟弟家的孩子，这几天忙坏了。蓬仙一听就笑了，那不是她亲生女吗？又问那邻居，那孩子夜里闹不闹？邻居说，怎么不闹？夜里闹得左邻右舍都睡不着。蓬仙一听就不说话了，心里想，没生养过的女人就是不会带孩子。

蓬仙急急匆匆地又穿越半个城市，朝女会计所在的化工厂走去，走到半途上，奶汁涨得厉害，蓬仙就找个僻静处把奶汁挤掉了一半。大约午后两点钟左右，蓬仙闯进了化工厂，传达室的老头想拦住她盘问几句，蓬仙却急勿匆地往里面奔跑，她说，不喂不行了，要饿坏了，要饿坏了！老头在后面追着喊，你跑什么？什么饿坏了？蓬仙头也不回，边跑边叫了一声，我的孩子！

蓬仙来到了化工厂托儿所的窗外，一眼就看见小猫，一个保育员正拿着一瓶淡黄色的液体往小猫嘴里塞。蓬仙或许是急晕了头，一时竟然找不到托儿所的门，干脆就从窗子里翻了进去。里面的保育员惊呆了，纷纷过来围住了蓬仙，蓬仙也来不及解释，衣裳一撩就抢过了小猫。这样过了一分钟，母婴俩脸上都露出了一种轻快幸福的笑容。保育员们却仍然没醒过神来，七嘴八舌地盘问开了，你是陈会计的什么人？你是她弟媳妇吗？你是她请来的奶妈吗？

蓬仙不理睬这些问题，她伸出食指在婴儿脸上轻轻划了一圈，说，才两天不到，就瘦了一圈。又指着床上的奶瓶问，那瓶子里黄颜色的，是什么东西？保育员说，桔子汁呀，陈会计关照的，两点钟给孩子喂桔子汁。蓬仙一听火又窜上来了，她说，懂个屁，桔子汁也能顶饱？这么酸的东西，孩子的胃怎么受得了？孩子那胃比豆腐还嫩呀，这么喂孩子不得胃病才怪。蓬仙说话的嗓门很高，几个午睡的孩子被吵醒了，哇哇大哭起来，保育员们就请蓬仙到外面说话，蓬仙一边走一边说，这儿的孩子胆小，换了我家那些孩子，就是来个戏班子在他们床前唱戏打鼓，他们也不会哭一声。

到了外面蓬仙仍然抱着小猫，后来女会计闻讯赶来，看见蓬仙抱孩子的那模样那表情，她就预感到这个女婴已经不属于她了。蓬仙的目光冷冷地投射过来，充满了愤怒和轻蔑。

女会计说，你怎么找到这里来了？

蓬仙说，我要是不来，孩子是死是活还不知道呢。

女会计急了，她说，你怎么这样说话？孩子不是好好的吗？你以为就你的奶水值钱，孩子离了你就活不成啦？

蓬仙抱住小猫朝左边右边晃了几下，现在看来我的孩子离了我就是活不成。蓬仙的语气忽然变得平静，她抱着小猫走到女会计面前，说，我要带她回家，你要不要再抱一抱她？女会计绝望地扭过头去。你不要抱最后一下？蓬仙在女会计身边停留着，她脸上的表情像雨云一样急迟地变幻着，最后变成一丝悲哀的冷笑，她说，你也不怎么样，我还是看错人了。

女婴小猫就这样被她母亲又抱回了家，第二天我们街上那些好事的妇人来到冯家，她们叽叽喳喳地议论着女会计的那瓶桔子汁，蓬仙听得不耐烦了，她说，咳，喂点桔子汁也没什么了不起，我变卦也不是为了桔子汁，是她没经住我的考验，我让她抱孩子最后一下，我想看她抱孩子时哭不哭，她一哭我的心肯定软了，可是她不要抱，她不要抱，那个女人，她没经住我的考验呀！

小猫像一只小猫一样偎着蓬仙长大了。

冯家九个孩子中，蓬仙最疼爱的就是小猫，小猫的哥哥姐姐嫉妒她，吵起嘴来就说，你以为妈疼你？你刚生出来时差点让妈送给人家。小猫不相信，跑去问蓬仙，蓬仙笑着回答她，别听他们胡说，就是把他们八个都送人了，妈也不会把你送走的。

蓬仙到哪儿都带着小猫，蓬仙到哪儿小猫都跟着。小猫七岁那年跟着母亲去杂货后买扫帚，看见一个女人在柜台另一侧买凉席，那女人的手在凉席上一遍遍地搓摸着，眼睛却直勾勾地注视着自己。小猫有点害怕，就躲在蓬仙的身后不让她看见，等到那女人走出了杂货店，小猫就大声地问蓬仙，那人是谁？她为什么要盯着我看呢？

蓬仙沉默了一会儿，突然哈哈地笑起来，她在小猫脸蛋上拧了一把，说，她当然要盯着你看，看你长得漂亮不漂亮，看你懂事不懂事，你差点做了她的女儿嘛。

小猫瞪大了眼睛张大了嘴巴哇哇大哭起来，小猫还用新买的扫帚打母亲的屁股，蓬仙怎么哄也没用，一咬牙就使了个杀手锏，她高声喊道，再哭，你再哭我真的把你送给她，送给她去做女儿！

这下小猫被吓住了，小猫顿时止住了哭闹，她的两只手死死地抓住蓬仙的衣角。她的眼睛恐惧地望着杂货店门外，幸运的是那个女人已经拐过街角不见了，那个女人已经不见了。

蓬仙朝杂货店的女店员挤了挤眼睛，她说，没有办法，自己的孩子就得自己养。

那还用说吗？女店员不假思索地回答，那还用说吗？


# 良娼

作者：阿城

1

江老先生是哈尔滨的坐地户，乳名叫宝子，是瘸子。北方人给子女命名，多带宝字：大宝、三宝、宝珠、宝银。单是‘宝子’，母亲觉得生硬，就唤他“宝儿”。站在栅栏院里，冲街软软悠悠地喊：“宝儿——来家吃饭啦——”听着有些古色古香，暖了母亲的心。

江老先生的家在道外区。道外区的巷子很多，窄窄的，两面高墙，一色青砖，间有青苔漫着。江老先生的家临着江，是泥房单顶。只是很破旧了，四面危墙用杠子支着，是独门独院，北面临着一条热闹的街。院子抬掇得很干净。院子东西各植一株多花老桃树。恰春风越过万里长城，到了这里，只一夜的工夫，脱胎换骨，万朵齐绽，很爽眼，香了四邻。

母亲的二老仙逝，家徒四墙，院徒桃花，风兮，雪兮，终而沦落风尘，卖身以为生计。

母亲下海后，在家里接的第一位客人就是宋孝慈。宋孝慈背离妻子南北闯荡，陌路谋生，是济南人氏。很年轻。下了船，经人指点，就宿在这里。

是夜逢春，漫天爽着小雨。雨簇桃花，潇潇洒洒，播一庭清香。宋孝慈进来，收了油伞，撂了行囊，缓缓转首，见半掩在纱帐中的母亲，婉婉约约，一双秋瞳，两黛春山。惊了脸，心里叹了好一阵。

母亲见旅客两道箭眉，一身英气，且行止温文尔雅，心中落下许多安慰。便到灶上给他温了酒，又去院中剪了一辔雨下新韭，置两碟小菜又擀了面条，并格外卧了两个鸡子儿。端到桌上，说：“趁热”……说罢，便退到一旁替他烘烤半旧的湿衫。

道路坎坷，人世艰辛。宋孝慈稳稳地坐了；呷温酒，听雨声，品热面，觉得不似家中，胜似家中，便湿了眼。

“怎么干这个……”宋孝慈蔼声地问。

母亲说：“命呗。”

“怕么？”

母亲听了，心里烫烫的，不觉落了泪。

宋孝慈起身拉着母亲的手，坐在一起。

雨下得很精道，齐刷刷，松一阵，紧一阵，落到草房上，扑籁——扑籁，闷闷的，压得心里好沉。

宋孝慈在母亲这里住了两个多月，因囊中羞涩，心里实在盛不下母亲一片温情，便硬了硬心，找个借口，走了。

走的那天，也下着小雨。母亲擎着油伞，顺着多柳的江坝，一直把他送到道外的船坞。

在码头上，母亲把旅客给她的钱，分出大半给了他，说：

“穷家富路，带着吧。”

宋孝慈掂着掌中的钱，低了头，说：

“我还来……”

母亲笑了，只是柔柔地看他。

宋孝慈又说：“多保重。挣了钱，我就回来，把房子修修，太旧了，心里放不下……”

这一句，母亲没想到，半天哀着脸，说：“有你这句话，就够我享的了……你放心走吧。”

宋孝慈上了船，隔着雨，俩人都摆着手。

母亲想喊：我怀孕了——

汽笛一响，雨也颤，江也颤，泪就下来了。

四年过去，宋孝慈回来了，一领长衫更旧了，见了母亲，愧着脸、指着院里的房子说：

“这房子……我自己动手，修。”

母亲流了泪，嗔着脸，说：“见了我，也不问我好不好，就说房子

这年，江老先生四岁。伫立在一旁呆呆地看。

母亲说：“宝儿，这是你舅舅……”

四目相对，江老先生便觉得这一双眼睛亮亮的，很亲切，好像早就认得。

2

江老先生的母亲因是娼妓，便要常到“圈儿里”的小窑馆做生意。其实，母亲只能被叫着‘娼“。”妓“是兼以歌呀，舞呀，杂耍之类做饵，再兑之皮肉，钱来得很不容易，须有格外的本领。狎客一般都很下作，那事之先，必要令其歌舞杂耍一番，再给两个耳光，见精神了，闹到日上三竿。娼则不然。白天，在家里要干些粗活儿：洗衣呀，纺钱呀，揽些刺绣的手工活呀。到了掌灯时分，一律急急地换了新装，抹些粉脂、口红之类再半掩其门，一边干针线活儿，一边用眼睛瞟着街，候着。倘若家里无客，便顶着黑，急急地赶到春巷的小窑馆去，一并挤在穿堂的条凳上，再候。谓之”坐灯“。条凳后面是一檀色曲尺形高柜，里面歇着”老鸨“，专事笑脸，看茶，贺喜，收钱。狎客打开软帘，斜了进来，挨个地瞅，捏捏肩膀，端端下巴，皮松肉紧，决不含糊，严然相马。一俟中了意，便嚷：”干她。“

宋孝慈回来后，母亲就从不在家里接客，晚上就到圈儿里的小窑馆“坐灯”。宋孝慈就陪着江老先生在家里一道睡。白日里，他便光着脊梁，担水，和泥，脱坯，修房子，并苫了厚厚的房草，看上去，再挺个七年八年，没问题。闲下了，就剪修院庭中的那两株桃树。修剪得很仔细。浇水，施肥，松土。草木通情，给他抽出许多新技，姹紫嫣红，开得潇洒。每值早春，宋孝慈便要剪下一篮，领着江老先生到附近的“圈儿里”去卖。

道外的圈儿里一带，为哈尔滨有名的烟花柳巷，版图较大，桃红呀，柳绿呀，单是公娼就有 3000 多人。荟芳里、大观园你拥我挤，春楼鳞次。此局门外，常挂一牌：“两毛找四”。两毛钱一次云雨，是一般小窑馆的市价，一毛六就便宜了些，常常床不虚席。春楼外是一环形街道：卖彩线卖胭脂卖玉容宫皂，“上江土下江货，女招待七八个”、“专治鱼口横痃、五淋白浊”，以及缝裢补绽、洗浆衣物，连同各种瓜果梨桃，灿然锦色，往来梭织，鼎鼎沸沸。

宋孝慈挽着篮子，领着江老先生在街上款款地走。江老先生的眼睛便觉得有些不够使。舅舅说：

“宝儿，喊呐，啊？”

江老先生便冲着春接稚声稚气地喊：

“桃花来——桃花来：人则武士，花则桃花。买来——”

这后一句，是宋孝慈教的，很灵。狎客听了，就打开后窗：

“小瘸子，来两枝儿。”

卖罢了花，宋孝慈便领着宝儿到横街里的“万国饭店”去转转。

万国饭店，其实是一条专卖俗食的长棚，足二里。卖甚的都有：小米捞饭、高粱米豆饭、流浪鸡、花子肉、馄饨、切糕。切糕还分两种，一谓黄米切糕，以云豆合之。一谓江米切糕，佐以青、红丝果脯之类。都很享眼。舅舅驻了脚，蔼声地问：

“宝儿，想吃么？”江老先生一脸严肃，说：“再看看。”

舅舅便笑了，背起江老先生，说：

“走。吃面去。”

鸡丝面，是万国饭店的上品。很讲究，都是“双合胜”的嫂子面，海海一碗，有鸡丝、紫菜、蘑菇、海米、香油。有的卖主，还独出心裁，放上一二片黄梨，咯吱咯吱一嚼，很脆，开胃口，也养身子。一般圈儿里的狎客闹完了，都来吃它，并久之成俗。

舅舅并不吃，从旁边的菜摊，沽一碗浓浓的热茶，坐在条凳上慢慢地呷着，看着江老先生吃。

江老先生觉得舅舅真好。

母亲每每从圈儿里回来，舅舅总要给母亲做一碗热面，并卧上两个鸡子儿。再到灶上给母亲烧了洗脚水，候着。

吃罢了，洗罢了，母亲便倒在炕上死死地睡。舅舅悄悄地拉着江老先生，锁了院门，到松花江边去。

江天很阔。宋孝慈坐在江坝上，燃了一支烟，顺着眼，看着稳稳东逝的江水，瞅着江面上的千舟万揖，辛日无语。

江老先生玩得很快活。

春也去，秋也去，冬天便来了。

这一日，母亲见宋孝慈站在庭院的批干下发呆。就凑了过去，掸了掸他身上的青雪，柔下声来：

“他舅，眼瞅年关了。回家看看吧。”

宋孝慈低了头，沉吟半晌，说：

“我该出去闯闯运气，挣点钱，不能总让你遭这个罪……我也是男人嘛……”

母亲见他一脸的踟踌，知道他舍不下这里，心里嫩嫩的，热了好一阵，才说：

“你去吧。俗话说：人挪活，树挪死。”又说，“出去常想着我们……抽空捎个信儿，叫孩子知道，这世上还有个疼他的人。”

宋孝慈听了，硬下了脸，果决地说：“我不去啦！怎么还不是一辈呢！”

“孝慈哥，”母亲心里长长地叹了一口气，“我要是男人，就走。你不能光在这里瞎了自己的心思啊……将来，你出息啦，我当你的使妈就知足啦……”

宋孝慈去天津那日，母亲没去圈儿里接客。下黑，母亲把炕烧得好热。早早地吹了灯任着宋孝慈婴儿般地抱着，说了一夜的话。

清早起来，母亲给他煮了一盆热面，卧了六个鸡子。母亲说，“六”是个吉数：

六六顺。

吃罢了，母亲背着宝儿，过了霁虹桥，一直把他送到南岗的火车站。

那是冬天，没太阳。雪稳稳地下着，很厚实，足一尺。踩上去，咯咯吱吱，酸着牙根儿。母亲说：“火车上不比家，贼冷的，兜子里有瓶子白酒，挺不住就呷两口，热乎热乎，好。”宋孝慈点头：“哎。”车站的票房子是俄式建筑，黄色，大窗户，很浪漫，也很结实，房顶上也是厚厚的雪，一波一波的。天落得很低，火车的汽笛声和排汽声从那上面挤出来。宋孝慈说：“咱们照个相吧。有照相的。”母亲说：“不的啦，我的面孔很熟，旁人知道你同我会影，就容易错怪了你。”

最后还是照了。站到一起，母亲拽拽了他的衣襟儿，悄悄声，说：“孝慈哥，你雄着点……你走后，我拿出来看看，心里就踏实。”

3

宋孝慈走后，江老先生便觉得很孤单，看着庭院里的两株桃树也失了往日的精神，随着风，絮絮叨叨，听了，心里厌厌的，白日里母亲在家里时睡觉，江老先生便锁了院门，到松花江边去。

那时的松花江，水势极浩，沃沃野野，不但利之舟揖，且鱼虾之丰，也教人乍舌。江坝上，江老先生常常抱膝而坐，望江水东去，感渔舟唱晚，亦常常落泪。饿了，便沿着江边，拣些嫩小鱼虾，就着晚日的血色，啖了便是。吃罢，江天竟全暗下来，星星亦渐渐出齐。江老先生独自呆呆地看。

江老先生从小没人跟他玩。

江老先生的母亲，在圈儿里，每晚大约要待候 20 到 25 位客人。都是苦力，他们的日子也是不好过，有的脾气也不是很好，且个个有力气，母亲很累，很苦，被人活拆了似的。迷迷糊糊，闹不清上面忙的是张三还是李四的事常有。

嘴里只是念叨孩子：“宝儿……宝儿……”怕是这孩子又要睡到船仓里去了。

午夜时分，窑馆里给煮一碗面。这里亦是海海的一碗，威谈还好，很热，烫嘴。

但须快吃。不然，误了急客，跳了脚，老鸨便要使眼珠子。古人说：“农不如工，工不如商，商不如依门卖笑。”说得很优美。母亲吃的，常常要留下半碗，第二天热了，给江老先生。母亲说：“这是细粮，你仔细着吃么。这样慌张，怎么能品出味道来呢？”说罢，还要长叹一口气，自言自语地说：“一点儿也不像你舅舅。”

江老先生觉得母亲老了，脸色也不是很好……

4

八年过去，九年春上，江老先生 14 岁的时候，宋孝慈回来了，那时母亲已过世两年了。庭院里败草枯枝，两株桃花也随着母亲去了。只留得两架枯干矗在那里。那天春风很大，松花江正在爆起冰排，隐隐约约，轰轰地响。泥房上厚厚的房草、被风一绺一绺地掀，在半天上随着风“咝咝”地叫。

乞儿似的江老先生看着站在庭院里的宋孝慈，已经不认得了，笑着说：

“先生，我妈早死了，你上圈儿里去吧，那有女人。”

“宝儿……”宋孝慈失了声，“宝儿，你不认得舅舅了？”

江老先生怔住了，缓过腔来，立刻奔到枯死的桃树下，死死地抱着树干，放开喉咙，野野地喊：

“妈——舅舅回来啦——”

“妈——你听着没有——”

宋孝慈僵了脸，问：

“宝儿——你怎么啦？”

江老先生松了树干，转过身来，竟是一脸的泪：

“舅舅，妈说，你回来了，让我在桃树下告诉她一声……她说，她能听着……”

这一夜，宋孝慈同宝儿说了好多。宋孝慈问：

“宝儿，你妈临终前，留下什么话了么？”

“妈给我留了你的地址，告诉我：不到饿死，不去找你。”

宋孝慈听了，泪水止不住，就任着碗蜒下去……

翌年。宋孝慈办了“东亚棉纺公司”。家眷也从外地迁了来。并把江老先生带到厂里，让他当了更夫。

江老先生很懂事，人前人后，从不管他叫舅舅。

宋孝慈总是稳着脸，很严肃，做事也很精明。听厂里人说，他的公司是天津宋裴卿的子公司（说不准）。晚上一有空暇，他便到更房来看江老先生。江老先生远远地见他来了，便躲了。宋孝慈见更房锁着门，就坐在外面的条凳上，燃支烟，吸罢了，再燃一支，见江老先生仍未回来，心里就明白了许多，便站了起来虚着身子，冲着暗处，哑着声喊：

“宝儿——有事，就去找舅舅……”

江老先生在暗处，听得真真切切。心里有话：“妈，你也听见了吧？

东亚公司于当时工人的眼里，是很不错的。厂房的山墙上高悬着：“己所不欲，勿施于人”；“你愿人怎样待你，你就先怎样待人”几个繁体大字，均为紫蓝色，并用白油漆框着，很艺术。公司的每个职工手中都有一本宋孝慈亲自撰写的《东亚铭》。这一切，江老先生都记忆犹新，并感悟到许多东西，遵守得也一丝不苟。有些条文，江老先生竟能倒背如流：

主义：人无高尚之主义，即无生活之意义。事无高尚之主义，即无存在之价值。

团体无高尚之主义，即无发展之能力。

作事：人若不做事，生之何益！人若只作自私之事，生之何益！人若不为大众作事，生之何益！人若只为名利作事，生之何益！

逝者如斯夫——

宋孝慈是哈尔滨光复前去的台湾。临行前，偕同江老先生到了荒山坟场。

坟场很好。尤属一轮混血般的晚照悠悠地悬在西头，就更壮眼：阔阔地展开，一坟一枝牵连不断，杂乱且有法度；荒荒疏疏的蒿草之中，间有昆翅的婆裟与鸣叫。

北方文化：凡做奸犯科连同娼娼妓妓者，断气后，都要埋在另一场，免得乱了阴宅的纲常。

母亲的坟就置在另一场，是阴面，有丑丑的碎石散散地簇着。母亲是良娼，碑就有些支撑不住，吃力地挺在那里，随着风，喘着，时断时续。碑文只五个字：

江桃花之墓

宋孝慈软了腿，勾头在地，恸着。

母亲用自己的碑影罩住他，深深地抚……

跪在一旁的江老先生说：

“妈，舅舅又要走了，我陪他来，是向你辞行的……”

宋孝慈听着，禁不住，就放声嚎哭起来。

晚照，血血地洇着。

宋孝慈涕泪交叠，苦揪着脸，说：

“宝儿他娘，我还回来……”

祭过母亲，宋孝慈拉着江老先生的手，说：

“宝儿，你妈生前有话，把你交付给我……眼下兵荒马乱，生意不好做了，跟舅舅一块去台湾吧。在那再办个厂……”

江老先生看着母亲的坟，用心想了一阵，转过头来，说：“我是个瘸子，就不去了……舅舅，你走吧……”

后记

宋孝慈走后不久，哈尔滨就光复了。江老先生因是瘸，被新接管的领导仍安排当更夫。1954 年，宋孝慈给江老先生转寄了一笔钱，同年，因心脏病死于台湾。真名叫李春林。

莫道世人容易老，青山也有白头时。江老先生已年逾六旬喽，动作也迟缓了，话极少，显得很谦和。厂里的工人称他“老先生”。

江老先生是去年死的，就死在更房里，脸上永远是老人的慈祥。

遗物中有一本很旧的《东亚铭》，厂长拿在手里，端详一阵，对工会负责后事的人说：“其它的，都随葬。这个——我留下！”

江老先生享年 63 岁。一生未娶。

江老先生在道外处的老宅，被区政府易为饭馆，名叫“临江居”。


# 自信

作者：蔡澜

第一次见成龙，是在电影摄影棚里。一条古装街道，客栈、酒寮、丝绸店、药铺。各行摊档，铁匠在叮叮当当敲打，马车夫的呼呼喝喝，俨如走入另一个纪元，但是在天桥板上的几十万烛火刺眼照下，提醒你是活在今天。

李翰祥的电影，大家有爱憎的自由。一致公认的是他对布置的考究是花了心血，他对演员的要求很高，也是不可否认的。

现在拍的是西门庆在追问郓哥的那一场，前者由杨群扮演，后者是个陌生的年轻人，大家奇怪，为什么让一个龙武师来演这么重的文戏？

开麦拉一声大喊，头上双髻的小郓哥和西门庆的对白都很精彩。一精彩，节奏要吻合，有些词相对地难记，但是两人皆一遍就入脑，没有 NG 过。李导演满意地坐下：“这小孩在朱牧的戏里演店小二，给我印象很深，我知道他能把这场戏演好，怎么样？我眼光不错吧？”

成龙当了天皇巨星以后，这段小插曲也跟着被人遗忘。

这次在西班牙拍外景，我们结下了片缘，两人用的对白大多数时间是英语。

为什么？成龙从前一句也不会讲，后来去美国拍戏用现场同步收看，又要上电视宣传，恶补了几个月，已能派上用场。回来后，他为了不让它“生锈”，一有机会就讲。

他说：“我和威利也尽可能用英语交谈。”

“我们两人都是南洋腔，你不要学坏了哟。”我笑着说。

“是呀！你们一个新加坡来，一个马来西亚人，算是过江龙，就叫你们做新马仔吧！”成龙幽了我们一默。

从故事的原意开始，成龙已参加。后来发展为大纲、分场、剧本、组织工作人员、看外景、拍摄，到现在进入尾声，已差不多半年，我们天天见面，认识也有一二。但是，要写成龙不知如何下笔，数据太多，又挤不出文字，就把昨天到今晨，一共十几个小时里所发生的事记录一下。

我们租了郊外的一间大古堡拍戏。成龙已经赶了几日夜班，所以他今天不开车，让同事阿坤帮他驾驶。坐在车上，我们一路闲聊。

“你还记得李翰祥导演的那部古装片吗？”我忽然想起，

他笑着回答：“当然，大概是十年前的事了吧？那时候我也不明白李导演为什么会找我。杨群、胡锦、王莱姐都是戏骨子，我也不知道哪来的勇气，只好跟着拼命啰！”

“大家看了《A 计划》后，都在谈那个由钟塔上掉下来的镜头。到底真实拍的时候有多高？”我问。

“五十几英尺，一点也不假。”他说，“其实也没有什么了不起，我们拍之前用一个和我身体重量一样的假人，穿破一层一层的帐幕丢下去。试了一次又一次，完全是计计算好的。不过，等到正式拍的时候，由上面望下来，还是怕得要死。”

成龙并没有因为他的成名而丧失了那份率直和坦白。

到达古堡时天还没有黑，只见整个花园都停满演职人员的房车、大型巴士、发电机、化妆车。

灯光器材、道具、服装等等的货车，最少也有数十辆。

当日天雨，满地泥泞，车子倒退前进都很不容易。阿坤在那群交通工具中穿插后，把车子停下，然后要掉转。

成龙摇摇头：“不，不。就停在这里好了。”

“为什么？”阿坤不明白，“掉了头后收工时方便出去呀！”

“我们前面那辆是什么车？”成龙反问。

“摄影机车嘛！”阿坤回答。

成龙道：“现在外面下雨，水滴到灯泡会爆的，所以不能打灯，到了天黑，我们的车子对着它，万一助手要拿什么零件，可以帮他们用车头灯照照。”

阿坤和我都没想到这一点，因为当时天还是亮着。

进入古堡的大厅，长桌上陈设着拍戏用的晚餐，整整的一只烤羊摆在中间，香喷喷的。饭盒子还没有到，大家肚子咕咕叫，但又不能去碰它，这就是电影。

镜头和镜头之间，有打灯的空当，成龙没有离开现场。无聊了，他用手指沾了白水，在玻璃杯上磨，越磨越快，发出“嗡嗡”的声音，其他初见此景的同事也好奇地学他磨杯口，嗡嗡巨响，传到远方。

叫他去休息一下，他说：“我做导演的时候不喜欢演员离开现场。现在我自己只当演员，想走，也不好意思。”

宵夜来了，他和洪金宝、元彪几个师兄弟一面听相声一面挨干饭。听到惹笑处，倒在地上爬不起来。

天亮，光线由窗口透进来，已经是手工的时间，大伙拖着疲倦的身子收拾衣服。我向他说：“我驾车跟你的车。”

“跟得上吗？我驾得好快哟，不如坐我的车吧。”他说。

他叫阿坤坐后面，自己开。车上还有同事火星，火星刚考到驾照，很喜欢开车，成龙常让他过瘾，但今早他宁愿让别人休息。

火星不肯睡，直望公路，成龙说：“要转弯的时候，踩一踩煞掣，又放开，又踩，这样，车子自然会慢下来。要不然换三波、二波也可以拖它一拖，转弯绝对不能像你上次开那么快，记得啦！”

“学来干什么？”火星说。

“你知道我撞过多少次车吗？”成龙轻描淡写，“我只不过不要你重犯我的错误。”

成龙继续把很多开车的窍门说明给火星听，火星一直点头。

“我们现在天时、地利、人和都在，所以我才讲这么多。有时，我想说几句，又怕人家说我多嘴，还是不开口为妙。”最后，他还是忍不住再来一句，“开车最主要的是让坐在你车子里的人对你有自信，他们才坐得舒服。其实，做人，做什么事都是这一道理，你说是不是。”


# 黑羊

作者：伊塔洛 · 卡尔维诺

从前有个国家，里面人人是贼。

一到傍晚，他们手持万能钥匙和遮光灯笼出门，走到邻居家里行窃。破晓时分，他们提着偷来的东西回到家里，总能发现自己家也失窃了。

他们就这样幸福地居住在一起。没有不幸的人，因为每个人都从别人那里偷东西，别人又再从别人那里偷，依次下去，直到最后一个人去第一个窃贼家行窃。该国贸易也就不可避免地是买方和卖方的双向欺骗。政府是个向臣民行窃的犯罪机构，而臣民也仅对欺骗政府感兴趣。所以日子倒也平稳，没有富人和穷人。

有一天——到底是怎么回事没人知道——总之是有个诚实人到了该地定居。到晚上，他没有携袋提灯地出门，却呆在家里抽烟读小说。

贼来了，见灯亮着，就没进去。

这样持续了有一段时间。后来他们感到有必要向他挑明一下，纵使他想什么都不做地过日子，可他没理由妨碍别人做事。他天天晚上呆在家里，这就意味着有一户人家第二天没了口粮。

诚实人感到他无力反抗这样的逻辑。从此他也像他们一样，晚上出门，次日早晨回家，但他不行窃。他是诚实的。对此，你是无能为力的。他走到远处的桥上，看河水打桥下流过。每次回家，他都会发现家里失窃了。

不到一星期，诚实人就发现自己已经一文不名了；他家徒四壁，没任何东西可吃。但这不能算不了什么，因为那是他自己的错；不，问题是他的行为使其他人很不安。因为他让别人偷走了他的一切却不从别人那儿偷任何东西；这样总有人在黎明回家时，发现家里没被动过——那本该是由诚实人进去行窃的。不久以后，那些没有被偷过的人家发现他们比人家就富了，就不想再行窃了。更糟的是，那些跑到诚实人家里去行窃的人，总发现里面空空如也，因此他们就变穷了。

同时，富起来的那些人和诚实人一样，养成了晚上去桥上的习惯，他们也看河水打桥下流过。这样，事态就更混乱了，因为这意味着更多的人在变富，也有更多的人在变穷。

现在，那些富人发现，如果他们天天去桥上，他们很快也会变穷的。他们就想：“我们雇那些穷的去替我们行窃吧。”他们签下合同，敲定了工资和如何分成。自然，他们依然是贼，依然互相欺骗。但形势表明，富人是越来越富，穷人是越来越穷。

有些人富裕得已经根本无须亲自行窃或雇人行窃就可保持富有。但一旦他们停止行窃的话，他们就会变穷，因为穷人会偷他们。因此他们又雇了穷人中的最穷者来帮助他们看守财富，以免遭穷人行窃，这就意味着要建立警察局和监狱。

因此，在那诚实人出现后没几年，人们就不再谈什么偷盗或被偷盗了，而只说穷人和富人；但他们个个都还是贼。

唯一诚实的只有开头的那个人，但他不久便死了，饿死的。


# 猫人

作者：罗杰迪安 · 基瑟

我喜欢钓鱼。我最喜欢的钓鱼地点是在一个湖边，那个地方在加利福尼亚山区的一个城镇的小加油站附近，距我当初住的地方有三个小时的路程。

每年，冬雪刚刚融化，我便把渔具装上旅行车，出去钓一天鳟鱼。

有一次，我穿过美丽的人造高山湖泊的小水坝，把车开到一侧，开始卸下鱼竿。忽然，我听到一声枪响，呼啸着飞过我的头顶。听到有人开枪射击，让我大吃一惊，因为这是禁猎区，不允许打猎。另外，在我多年钓鱼的区域内，除了几辆拉木材的卡车路过，还是头一回遇到有人来。

我蹲在汽车后面，小心地瞭望四周，看是否有人。又响了两枪。子弹“砰砰”地击中大岩石，我却还是没有看到人。

随后，四个年轻人从土路上走来。一个人举起步枪，开了一枪。一只猫跑过土路，钻进灌木丛。

“嗨，你们到底在干什么？”他们走近了，我问他们，“这里不允许打猎。”

“只是打一只该死的猫。”大一些的青年说。另一个小青年慢慢举起枪，朝着那只猫又开了一枪，猫还藏在大石块后面。

“别胡扯，伙计们。为什么没来由地要杀生？”我问。

“让你看，那只猫值多少钱？”一个小青年说。

“十元怎么样？”我说。

“砰！”朝着猫的方向又是一枪，“一百元怎样？这个价钱可以接受。”四个年轻人中最大的一个说，他朝着猫的方向又开了一枪。

几个星期来，我一直在攒钱，好去买一艘旧船和发动机，以便不必在岸上钓鱼了。我钱包里有一百一十元，口袋里有二十元。

“好吧，我给你们一百元买那只猫。只是请不要杀死它。”我掏出钱包，从秘密夹层拿出一百元，放在棕色旅行车的引擎盖上。四个年轻人走过来，站在那里盯着钱看。他们的脸上显出非常严肃的表情。大一些的小青年俯身拿起钱来，揣进牛仔裤的口袋。

四个年轻人消失在路的拐弯处，我开始寻找那只猫。

几分钟后，男孩们乘坐一辆旧的敞篷小货车从我身边驶过，回山上的镇子。

用了一个多小时，我才给了那只猫足够的信任，抓到了它。我抚摸它五分钟左右，随后放进我的车里，连带我的渔具，开车回到山上的小店。

我问店主，他是否知道周围有人丢了一只猫。他走到我的车旁，看那只猫。他告诉我，住在隔壁的老人大约一星期前丢了自家的猫。老人很伤心，因为那是他妻子的猫，她在几个星期前去世，那只猫是她留下的全部纪念。

小店店主到电话机旁，打了一个电话。他回来时，给我倒了一杯热咖啡，我们聊了大约十分钟。我听到身后的门开了，我转过身。

一位花白头发的老人，弯腰驼背，看上去至少有一百岁了，慢慢地走到拐角处。他坐在一张摇椅上，却一言不发。

“那是他的猫。”店主告诉我。

老人用手杖敲了三下地板。店主从柜台后出来，走到老人坐着的地方。老人跟店主耳语了几句，随后递给他一张纸。店主扶着老人的手臂，帮他站起来，他们走向外面的旅行车。

我透过窗户看到老人伸手进去，拿起那只猫，抱在胸前。随后，两个人走到隔壁的一栋活动住房，走了进去。几分钟后，店主回来。

“我真该上路了。”我告诉他。

“找到那只猫有奖励。”店主说。

“我不想要奖励。”我回答。

店主拿出一张纸，我从他手里接过来。我打开折叠的纸，看到那是一张私人支票，可以兑换成“现金”，上面写着 2500 元！

我吃惊地扬起眉毛。“别担心，那张支票无效。从他妻子去世后，这个老人精神错乱了。”店主说。

我把支票对折，扔到柜台上，好让他扔掉。其后，我的内心告诉我把支票留下来。我把支票拿回来，放到衬衣口袋里。

“我想，只有傻瓜才认为一只猫值那么多钱。”他说着，大笑起来。

“是呀，我知道。只有傻瓜才这么想。”我说着，也笑了。

我走出门，钻进旅行车，开车回家。男孩和他们的枪让我决定推迟钓鱼旅行，另找时间。

我到家时，妻子给我一张字条，是一位来访的朋友留下的。字条上说他认识一个人，愿意把自己的船卖给我，可按月付款。我给那位卖船的人打电话。说完船的情况，我问他想要多少钱。

“两千五百元。要是我替你筹措资金，就是三千元。”他告诉我。我对他说，过一个小时后再给他打电话。

我从口袋里拿出支票，给我存款的银行打电话。我告诉他们猫的故事，问他们是否有办法查出老人给我的支票是否有效。我把支票的号码报给他们，等着他们回话。十分钟后，电话打回来了。

“基瑟先生，支票有效。”那头的女士说着，笑了。

“有什么好笑的？”我问她。

“噢，我给银行打电话，询问这张支票是不是真的，那位先生笑了。他告诉我，那位给你支票的老人特别富有。他拥有在加利福尼亚地区经营的大部分木材公司。”

这还不是唯一的惊喜。那天晚上，我驱车去看待售的船、发动机和拖车。揭开帆布时，那条船跟新的一样。这笔买卖很划算，我知道自己想要它。但是，我看到船的名字，我确定注定要这条船。

船的后面漆着的字是：猫人。


# 斜眼

作者：毕淑敏

没考上大学，我上了一所自费的医科学校。开学不久，我就厌倦了。我是因为喜欢白色才学医的，但医学知识十分枯燥。拿了父母的血汗钱来读书，心里总有沉重的负疚感，加上走读路途遥远，每天萎靡不振的。

“今天我们来讲眼睛……”新来的教授在讲台上说。

这很像是文学讲座的开头。但身穿雪白工作服的教授随即拿出一只茶杯大的牛眼睛，解剖给我们看，郑重地说：“这是我托人一大早从南郊买到的。你们将来做医生，一要有人道之心，二不可纸上谈兵。”随手尽情展示那个血淋淋的球体，好像那是个成熟的红苹果。

给我们讲课的老师都是医院里著名的医生。俗话说山不在高，有仙则灵。但教授演示到我跟前时，我故意眯起眼睛。我没法容忍心灵的窗口被糟蹋成这副模样。从栅栏似的睫毛缝里，我看到教授质地优良的西服袖口沾了一滴牛血，他的头发像南海观音的拂尘一般雪白。

下了课，我急急忙忙往家赶。换车的时候，我突然发现前面有一丛飘拂的白发。是眼科教授！我本该马上过去打招呼的，但我内心是个孤独羞涩的女孩。我想只上过一次课的教授不一定认识我，还是回避一下吧。

没想到教授乘车的路线和我一样。只是他家距离公共汽车站很远，要绕过我家住的机关大院。

教授离开了讲台，就是一个平凡的老头。他疲惫地倚着椅子扶手，再没有课堂上的潇洒。我心想他干脆变得更老些，就会有人给他让座了。又恨自己不是膀大腰圆，没法给老师抢个座。

终于有一天，我在下车的时候对教授说：“您从我们院子走吧，要近不少路呢。”

教授果然不认识我，说：“哦，你是我的病人吗？”

我说：“您刚给我们讲过课。”

教授抱歉地笑笑：“学生和病人太多了，记不清了。”

“那个院子有人看门。让随便走吗？倒真是节约不少时间呢。”教授看着大门，思忖着说。

“卖鸡蛋的、收缝纫机的小贩，都所向无敌。您跟着我走吧。我们院里还有一座绿色的花园。”我拉着教授。

“绿色对眼睛最好了。”教授说着跟我走进大院。

一个织毛衣的老女人在看守着大门。我和教授谈论着花草经过她身边。我突然像被黄蜂蜇了一下——那个老女人乜斜着眼在剜我们。

她的丈夫早就去世了，每天斜着眼睛观察别人，就是她最大的乐趣。

从此，我和教授常常经过花园。

一天，妈妈对我说：“听说你天天跟一个老头子成双成对地出入？”

我说：“他是教授！出了我们大院的后门就是他的家。那是顺路。”

妈妈说：“听说你们在花园谈到很晚？”

“我们看一会儿绿色。最多就是一套眼睛保健操的工夫……”我气愤地分辩，不是为了自己，而是为了教授。

妈妈叹了一口气说：“妈妈相信你，可别人有闲话。”我大叫：“什么别人！不就是那个斜眼的老女人吗！我但愿她的眼睛瞎掉！”

不管怎么说，妈妈不让我再与教授同行。怎么对教授讲呢？我只好原原本本和盘托出。“那个老女人，眼斜心不正，简直是个克格勃！”我义愤填膺。

教授注视着我，遗憾地说：“我怎么没有早注意到有这样一双眼睛？”他忧郁地不再说什么。

下课以后，我撒腿就跑，竭力避开教授。不巧，车很长时间才来一趟，像拦洪坝，把大家蓄到一处。走到大院门口，教授赶到我面前，说：“我今天还要从这里走。”

知识分子的牛脾气犯了。可我有什么权力阻止教授的行动路线？“您要走就走吧。”我只有加快脚步，与教授分开走。我已看见那个老女人缠着永远没有尽头的黑毛线球，阴险地注视着我们。

“我需要你同我一起走。”教授很恳切很坚决地说。作为学生，我没有理由拒绝。

我同教授走进大院。我感到不是有一双而是有几双眼睛乜斜着我们。斜眼一定是种烈性传染病。

“你明确给我指一指具体是哪个人。”教授很执著地要求。

我吓了一跳，后悔不该把底兜给教授。现在教授要打抱不平。

“算了！算了！您老人家别生气，今后不理她就是了！”我忙着劝阻。

“这种事，怎么能随随便便就放过去了呢？”教授坚定不移。

我无计可施。我为什么要为了这个斜眼的女人，得罪了我的教授？况且我从心里讨嫌这种人。我伸长手指着说：“就是那个缠黑线团的女人。”

教授点点头，大踏步地走过去。“请问，是您经常看到我和我的学生经过这里吗？”教授很客气地发问，眼睛却激光般锐利地扫描着老女人的脸。

在老女人的生涯里，大概很少有人光明正大地来叫阵。她乜斜的眼光抖动着：“其实我……我……也没说什么……”

教授又跨前一步，几乎凑近老女人的鼻梁。女人手中的毛线球滚落到地上。

文质彬彬的教授难道要武斗吗？我急得不知如何是好。这时听见教授一字一顿地说：“你有病。”

在北京话里，“有病”是个专用词语，特指有精神病。

“你才有病呢！”那老女人突然猖狂起来。饶舌人被抓住的伎俩就是先装死，后反扑。

“是啊，我是有病，心脏和关节都不好。”教授完全听不出人家的恶毒，温和地说，“不过我的病正在治疗，你有病自己却不知道。你的眼睛染有很严重的疾患，不抓紧治疗，不但斜视越来越严重，而且会失明。”

“啊！”老女人哭丧着脸，有病的斜眼珠快掉到眼眶外面了。

“你可不能红嘴白牙地咒人！”老女人还半信半疑。

教授拿出烫金的证件，说：“我每周一在眼科医院出专家门诊。你可以来找我，我再给你做详细的检查治疗。”

我比老女人更吃惊地望着教授。还是老女人见多识广，她忙不迭地对教授说：“谢谢！谢谢！”

“谢我的学生吧。是她最先发现你的眼睛有病。她以后会成为一个好医生的。”教授平静地说，他的白发在微风中拂尘般飘荡。

从乜斜的眼珠笔直地掉下一滴水。


# 识人

作者：蔡澜

人活到老了，就学会看人。

看人是一种本事，是累积下来的经验，错不了的。

古人说：人不可貌相。我却说：人绝对可以貌相，我是一个绝对以貌取人的人。

相貌也不单是外表，是配合了眼神和谈吐，以及许多小动作而成。这一来，看人更加准确。

獐头鼠目的人，好不到哪里去，和你谈话时偷偷瞄你一眼，心里不知打什么坏主意，这些人要避开，愈远愈好。

大老板身边有一群人，嬉皮笑脸地拍马屁，这些人的知识不会高到哪里去。虽然说要保得住饭碗，也不必做到这种地步，能当得上老板的人，还不都是聪明人？他们心中有数，对这群来讨好自己的，虽不讨厌，但是心中不信任，是必然的事。

说教式地把一件不愉快的事重复又重复，是生活刻板的人，做人消极的人，这种人尽量少和他们交谈，要不然你的精力会被他们吸光。

年轻时不懂，遇到上述这些人就马上和他们对抗，给他们脸色看，誓不两立，结果是给他们害惨。现在学会对付，笑脸迎之，或当透明，望到他们背后的东西，但心中还是一百个看不起。

美丑不是一个很大的关键。

我遇到很多美女，和她们谈上一个小时，即刻知道她们的妈妈喜欢些什么、用什么化妆品、爱驾什么车。她们的一生，好像都浓缩在这短短的一小时内，再聊下去，也没有什么话题。当然，在某种情形之下，你不需要很多话题。

丑人多作怪是不可以原谅的。几乎所有的三八婆都是这一个典型。和她们为伍，自己总会变成一个，一字曰八，总之总之，碰不得也。

愁眉深锁的女人，说什么也讨不到她们的欢心，不管多美，也极为危险，这些人多数有自杀倾向，最怕是有这个念头时，拉你一块走。

这种女人送给我，我也不要。现实生活中也会遇到的，像林黛玉和乐蒂等人，都是遗传基因使她们不快乐。

大笑姑婆很好，她们少了一根筋，忧愁一下子忘记，很可爱的。不过多数是二奶命，二奶又有什么不好？她们大笑一番，愉快地接受了。

爱吃东西的人，多数不是什么坏人。他们拼命追求美食，没有时间去害人。大笑姑婆兼馋嘴，是完美的结合，这种女人多多益善。

样子普通，但有股灵气的女人，最值得爱。什么叫有灵气？看她们的眼睛就知道，你一说话，她们的口还没有张开之前，眼睛已动，眼睛告诉你她们赞不赞成。即使她们不同意你的看法，也不会和你争辩，因为，她们知道，世界上要有各种意见，才有趣。

我们以前选新人，六七十年代中一部片就是上千个，有谁能当上女主角，全靠她们的一双眼睛，有的长得很美，但双眼呆滞，没有焦点，这种女人怎么教，都教不会演一个小角色。

自命不凡，高姿态出现的女强人最令人讨厌――她当身边的人都是白痴，只有自己一个才是最精的。这种女人不管美丑，多数男人都不会去碰她们。从她们脸上可以看出荷尔蒙的失调。

“我还很年轻，要怎么样才学会看人？”小朋友常这么问我。

要学会看人，先学会看自己。

本人一定要保存一份天真。

像婴儿一样，瞪着眼睛看人，最直接了。

沉默最好，学习过程之中，牢牢记住就是，不要发表任何意见，否则即刻露出自己无知的马脚。

注视对方的眼睛，当他们避开你的视线时，毛病就看得出来了。

也不是绝对地不出声。将学到的和一位你信得过的长辈商讨，问他们自己的看法对与不对。长辈的说法你不一定赞同，可以追问，但不能反驳，否则人家嫌你烦，就不教你。

慢慢地，你就学会看人了，之中你一定会受到种种的创伤，当成交学费，不必自怨自艾。

两边腮骨突出来的，所谓的反腮，是危险的人，把你吃光了骨头也不吐出来。以前我不相信，后来看得多，综合起来，发现比例上坏的实在占多。

说话时只见口中下面的一排牙齿，这种人也多数不可靠。

一眼看上去像一个猪头，这种人不一定坏，但大有可能是愚蠢的、怕事的、不负责任的。

从不见笑容，眼睛像兀鹰一样的，阴险得很，德国的希特勒，就是例子。

什么时候学会看人，年纪大了自然懂得。当你毕业时，照照镜子，看到一只老狐狸。

我就是一个例子。


# 身价

作者：欧 · 亨利

傍晚，一位身穿灰色衣服的女孩，又来到了小公园安静的角落里，坐在一张长椅子上开始读书。她的脸看起来很秀气，衣服却很普通。小伙子知道，这一段日子，她每天都是如此。

小伙子慢慢地走到她旁边，就在这时，女孩手中的书滑落到了地上。小伙子顺势捡起书，礼貌地递给她，寒暄了几句后，就静静地站在一边。

女孩看了一眼小伙子，一身俭朴的衣着，一张并不引人注目的脸。

“坐下吧，如果你不介意的话。光线太暗了，看不了书，我愿意聊聊天。”

“你知道吗，”小伙子说，“你是我见过的最漂亮的女孩，我昨天就看见你了。”

“不管你是谁，”女孩冷若冰霜地说，“都得记住，我受过良好的教育。”

“对不起，”小伙子说，“都是我不好，我太冒昧了，我的意思是，来公园的女孩很多，你知道，当然，你不知道，但是……”

“我当然知道。还是谈点别的吧，讲讲这些来来往往的游客，他们要去哪儿？为什么那么匆忙？他们高兴吗？”

小伙子一下糊涂了，不知道自己究竟应该扮演一个什么样的角色。

“我之所以经常来这里，就是因为在这里可以和游客们近距离地接触。我跟你讲话，就是因为我想找一个天性善良，对钱看得很淡的人聊一聊。你不知道，我太讨厌钱了，也讨厌我周围那些腰缠万贯的男人。我不喜欢珍珠宝石，对游山玩水也没什么兴趣。”

“可我总是认为，”小伙子说，“钱是个好东西。”

“当你有了一百万之后，就只好兜风、看戏、跳舞、赴宴去了。我可不想过这种日子。”

小伙子诙谐地看着女孩，说：“我很喜欢研究和探听你们富人的生活。”

“有时候，”女孩继续说，“我想，如果我要恋爱，就要爱一个普通的小伙子——告诉我，你是干什么的？”

“我就是个普通人，但是我希望我能出人头地。你刚才说的话当真吗？你会爱一个普通人？”

“当然啦！”她回答。

“我在一家小饭馆工作。”小伙子说。

“该不会是个跑堂的吧？”女孩问。

“差不多。”

女孩马上看了看手表，然后站起身，说：“你怎么还不去工作？”

“离上班时间还有一个小时呢。我们，我们下次还可以见面吗？”

“不知道……哦，我得走了，晚上我还要去赴宴，还有一个音乐会，司机在等着我呢。”说到这里，她朝公园门口的那辆白色小轿车指了指，“那是我的车。”

“我看到了。”小伙子羡慕地说。

“再见！”

“天晚了，”小伙子说，“不太安全，要不，我送你？”

“谢谢，你还是再坐一会儿吧。”说完，女孩朝着公园大门走去。小伙子看着女孩的身影，不紧不慢地跟在她后面。

到了公园门口，女孩从那辆白色小轿车旁走了过去，横穿马路，走进一家小饭馆，打了卡，然后换上侍应生的制服，开始工作。

小伙子在街上慢慢地走了一会儿，然后，径直走近那辆白色轿车，钻进去，对司机说：“去夜总会，亨利。”




---

[Next Page](/llms-full.txt/1)

