本节摘要:突变是进化的原材料,但它有自己的"统计学性格":类型分布高度不均、速率数量级极低但从不为零、方向与生物的需要无关。本节按尺度从小到大清点各类突变,用代码模拟一个简化的复制错误模型,看突变谱如何自然形成,并解释移码、重复、倒位这些"大突变"为何在进化上远比点突变更具戏剧性。
DNA 每次复制要拷贝约三十亿碱基,聚合酶的校对系统把错误率压到每碱基每代约百亿分之一。剩余的错误来源还有三类:化学损伤(脱氨、氧化)、物理因素(紫外线诱导二聚体)、可移动元件(转座子)的插入。进化学关心的是净结果:每个基因组每代约新增几十个突变,其中发生在编码区、且改变氨基酸的,只是少数。
关键澄清"随机"一词:突变随机,指的是与个体的需要无关——生活在抗生素环境中的细菌,并不会因此更多地产出耐药突变。但这不等于"没有概率结构":不同类型的突变发生率差异极大,转换多于颠换、重复序列间更易滑链。第 5 章的分子钟正是建立在这种速率的相对稳定性上。
| 尺度 | 类型 | 典型后果 | 进化角色 |
|---|---|---|---|
| 碱基 | 同义替换 | 无氨基酸改变 | 中性演化主力,分子钟原料 |
| 碱基 | 错义/无义替换 | 单氨基酸改变/提前终止 | 微调或破坏功能 |
| 短片段 | 插入/缺失(indel) | 移码,整段读框重排 | 多数有害,偶创新域 |
| 短片段 | 重复扩张 | 拷贝数变化 | 基因剂量、驯化表型 |
| 染色体 | 倒位 | 抑制区内重组、锁定等位组合 | 适应基因打包传播 |
| 染色体 | 基因/基因组重复 | 冗余拷贝获得自由 | 新基因诞生的主通道 |
| 基因组 | 多倍化 | 整套染色体加倍 | 植物物种形成的爆发器 |
注意"基因重复"一行:一份拷贝维持原功能、另一份自由积累突变,是新功能基因(如嗅觉受体家族、血红蛋白簇)的主要来源。进化的大部分"创新"走的不是改旧零件,而是复制后特化。
import random def replication(seq, sub_rate=0.001, indel_rate=0.0002, rng=None): """一轮复制:碱基替换 + 插入缺失,返回新序列与事件记录""" rng = rng or random.Random() bases = "ACGT"; new = []; events = [] i = 0 while i < len(seq): b = seq[i] r = rng.random() if r < sub_rate: # 替换 nb = rng.choice([x for x in bases if x != b]) new.append(nb); events.append(("sub", i, b, nb)) elif r < sub_rate + indel_rate and rng.random() < 0.5: new.append(b); new.append(rng.choice(bases)) # 插入 events.append(("ins", i, "-", "-")) elif r < sub_rate + indel_rate: events.append(("del", i, b, "-")) # 缺失,跳过该碱基 else: new.append(b) i += 1 return "".join(new), events rng = random.Random(5) lineage = "ATGCGTACGTATCGATCGATCGTAGCTA" * 10 # 300 碱基祖先 total = {"sub": 0, "ins": 0, "del": 0} for gen in range(50): # 50 代传递 lineage, ev = replication(lineage, rng=rng) for e in ev: total[e[0]] += 1 print("50 代累计突变谱:", total, " 序列长度变为", len(lineage))
典型输出是替换数十个、插入缺失若干、序列长度轻微漂移。把 indel_rate 调高一个数量级再跑,长度开始明显增减不定——这就是为什么 indel 富集区(如微卫星)是法医与群体遗传学的高信息量标记。
import random def mutation_effect(rng): """粗粒化模型:突变落点决定效应分布""" where = rng.random() if where < 0.60: return "中性" # 非编码或同义 if where < 0.90: return "轻微有害" # 编码区扰动 if where < 0.99: return "明显有害" return "轻度有利" rng = random.Random(11) from collections import Counter c = Counter(mutation_effect(rng) for _ in range(10000)) for k, v in c.most_common(): print(f"{k}: {v/100:.1f}%")
一万次抽样里,"有利"约 1%,且强度轻微。这个分布有个重要推论:新突变的大多数命运是在漂变中悄悄消失,能被选择抓住的只是极小尾部。进化因此必然是"大量试验 + 极少数留存"的过程,而不是定向改造。
⚠️ 常见坑:把"突变率低"误解成"进化速度的上限"。进化速率取决于突变供给与选择/漂变的放大速度之积;果蝇适应辐射的速率远高于其突变率单独允许的量级,因为群体里有大量潜伏的既有变异(standing variation)可供选择。
下一节补上从序列到性状的最后一环:表达与调控,以及表观遗传对"遗传"概念边界的扩展。
值得亲手跑的两个变式。变式一:把演练一的 sub_rate 与 indel_rate 同时乘 10,观察"突变谱的形状"是否改变——在低速率区间两者比例稳定,序列长度近似守恒;高速率区间 indel 累积开始压过替换,序列长度漂移加剧。真实的超快进化序列(如某些 RNA 病毒的基因组)就生活在后一种状态下,这也解释了它们为何难以用常规比对分析。
变式二:在模拟里加一条规则——插入若发生在三联体读框内、长度非 3 的倍数则触发移步惩罚(丢弃该 lineage),可观察到"读框约束"如何强力过滤 indel 存活。真实编码区恰恰表现出这种不对称:indel 富集在内含子与基因间区,编码区几乎只有替换。约束的分布本身就是功能的影子,这个观察直接通向第 5 章 dN/dS 的设计逻辑。