第1章 生男生女到底能不能控制?怎么控制?

【自我介绍】

各位朋友,大家好,我是 Merily 博士。我毕业于中国科学院,留学于美国卡耐基研究所,后来又在美国顶尖的索尔克生物研究所从事博士后研究,我研究的主要方向是细胞生物学,胚胎发育学等领域,现在我在美国的一家医学中心担任辅助受孕顾问,帮助患者如何实现更好的孕育。

【课程的目的】

因为工作和生活的原因,我经常会接触到很多美国家庭,深刻地感觉到由于中美文化差异和信仰的不同,美国人的生育观念跟咱们中国人还是很有区别的,比如说,一般美国人并没有「养儿防老」这个概念,也没有「不孝有三,无后为大」这样的舆论压力;整体来讲,妇女在家庭中的地位也还是比较平等的。但就生男孩儿还是生女孩儿这件事,咱们不妨来猜一下,美国人到底有没有诉求呢?

按照我们的理解,美国人应该不在意孩子性别吧,对这个应该是很随意、很开放的吧?但是实际上,美国也有相当一部分家庭,对生男生女有诉求,他们特别渴望得到一定性别的孩子,或者是男孩儿,或者是女孩儿,尤其已经有一个孩子或者多个孩子的家庭,对性别选择的要求就更加强烈。

但是他们的出发点,更多的只是单纯的喜欢男孩或者女孩,或者想要儿女双全,跟咱们中国的传统宗族观念下的生男生女完全不一样。但是不管怎么样,其实中国人和美国人,对生男生女这个事情,都还是有强烈意愿的。于是我在工作和生活中,也开始留心观察和研究,到底怎么才能生男生女,能不能在怀孕之前就想办法控制?而不是像以前那样,怀孕之后要通过流产才能来选择性别。因为从医学和伦理学的角度来看,全世界没有任何一个国家,会积极鼓励和提倡用有创性的手段来进行性别选择,尤其是流产。

所以我们要研究和观察的是,怎么样能让大家在自然受孕的过程中,采用一定的方法和技巧,或者遵循一定的规律,来最大可能的获得我们理想中想要性别的孩子,我想这对任何一个家庭都将是一件很美好的事情。

幸运的是科学家和生殖医学专家,确实发现了一些受孕过程中的有趣现象,通过对这些现象的观察和研究,他们也总结了一些方法,可以帮助大家大大提高生男或者生女的机率。这些方法不需要服用药物,不需要做有创性的检查,甚至有时候只需要一个体温计和一张纸、一只笔就够了。根据调查和回访,采用这些方法生男的成功率可以达到 80-90%,生女的成功率可以达到 70-80%。当然,尽管这个数据可能会有「幸存者偏差效应」,但是如果您极度渴望生男孩或者生女孩,这些方法还是值得尝试的。

这节课里,我把这些方法总结出来,教给大家,希望大家能够最大可能的得到自己理想性别的宝宝。当然,实现这个方法的前提是,一定要先了解生男生女的原理,以及人体受孕的过程。所以在这套课程的第二节和第三节,我会重点讲一下这些内容。您会发现,其实生男生女跟大家以前知道的可能不太一样,并不是简单的 X 精子和 Y 精子就决定了生男生女。包括人体的受孕过程,也有很多地方比想象的要神奇的多,正是基于这些奇妙的原理和现象,我们才能总结出相对有效的生男生女方法。在第四节里,我要教大家一些准备工作,这些准备工作非常重要,是生男生女能不能成功的关键和重要前提。在您做了充分的准备工作之后,就是最激动人心的实操课了。在第五节和第六节里,我会分别告诉您生男的方法和生女的方法,希望大家能够熟练掌握,大大提高生男生女的机率,早日实现自己的家庭梦想。

# 从流程图到程序:用 Pytho 编写顺序查找算法

前面学了一大堆变量啊,赋值啊,到底有什么用呢?

马上用处就来了——

## 修改顺序查找流程图——用变量和赋值替换其中的自然语言

### 以前的流程图

还记得我们之前已经学习了顺序查找算法吧(还记得吗)?

当时我们是画了一张流程图。先来回顾一下:

![eter image decritio here](htt://k.c/-9311-11e9-9417-f698e8a446d)

***流程图-1***

在这种图里,我们其实已经使用了数组(列表)变量 arr,和整型变量 i,只不过当时我们还不知道它们是**变量**,而仅仅将其当作数组和数组下标的形式化写法而已。

### 重画流程图

通过前面两章的学习我们知道,上图中大部分关于 arr 和 i 的操作就是对数组和整型变量赋值的。

在 Pytho 中我们用列表来实现数组操作,其实此处 arr 是列表类型的变量。而 le(arr)则是 Pytho 的一个内置函数,是用来计算列表长度的。

那么我们是不是可以利用已经学过的 Pytho 语言的要素,将上图中余下的自然语言文字也替换掉,都换成赋值语句或者内置函数的调用操作呢?

我们来试试:

![eter image decritio here](htt://k.c/90a410-9312-11e9-f22-7dc7821)

***流程图-2***

在程序开始的时候,先初始化两个变量:t——整型,目标数(target umer)和 arr——列表型,存放数列的数组。

然后给 i 赋初值 0,之后进入循环,循环的准入条件是 i 小于 arr 的长度——即元素个数。

在循环内部,将 t 和 arr[i]比较,如果相等则打印出对应元素的索引,然后退出循环(reak 表示退出当前循环),否则 i 递增 1 之后继续循环。

一旦到了 i 的值和 arr 的元素个数相等,就说明整个 arr 里面所有的元素都与 t 比较过,且都不相等,此时打印出「failed」告知用户查找失败了。

果然可以哦!

大家发现没有,上面这张重新画的流程图里,每一个矩形或者菱形框里面的内容,都变成了几乎可以直接写在程序中的语句。

因此,只要有办法把流程图中的控制结构写成程序语句,整个算法的实现就有了!

怎么在程序中体现顺序、条件、循环三种不同的结构呢?

## 关键字与控制结构

### 关键字

在介绍具体控制结构的写法之前,我们需要先了解一个概念——关键字!

**关键字(Keyword)**,也叫保留字(Reerved Word),是编程语言中的一类**语法结构**。

基本每一种编程语言都会有一系列关键字,它们在语言的格式说明里被预先定义,通常具有特殊的语法意义。

这些意义中非常重要的内容就是用来识别代码块、函数和流程控制结构。

### Pytho 的关键字

Pytho2 和 Pytho3 的关键字大体相同,既然用的是 Pytho3 我们只看 Pytho3 就好了。

其实,我们可以通过 Pytho 语句直接获得当前版本的关键字,具体代码如下:

imort keyword

rit()

这么简单的代码,我们直接在命令行运行就好了:

![eter image decritio here](htt://k.c/56c0af30-9317-11e9-9d-69ad1684fc56)

我们可以看到,Pytho3 的关键字总共有 33 个。这些关键字当然各有用处。

关于 Pytho 关键字的详解,网上到处都有,大家感兴趣可以自己搜索。

不过,作者认为,现在我们就是把每一个的作用都详细说一遍,你也记不住。不如先简单浏览一下,用到什么再具体学什么。

下面是从使用角度,对这 33 个关键字做的简单分类:

- 布尔类型字面量:

True

Fale

- 表示「不存在」的特殊型字面量:

Noe

- **关于流程控制**:

if

elif

ele

for

while

reak

cotiue

- 关于逻辑判断:

ad

or

ot

- 关于函数:

def

retur

yield

lamda

- 关于类型判断:

i

- 关于面向对象编程:

cla

a

- 关于代码块控制:

with ... a

- 关于 Lit 操作:

del

i

- 关于变量作用域:

gloal

olocal

- 关于异常处理:

aert

excet

fially

raie

try

- 关于导入模块:

from

imort

目前我们马上要用到的,就是控制流程相关的几个关键字。也就是 if,elif,ele,for,while,reak,cotiue。其中 if,ele 和 while 是最最基础的流程控制关键字。

我们现在就来看看,用这几个关键字,怎么构造各种流程控制结构。

### Pytho 中的三种控制结构

下面这几幅图就是直观的转换方法:

#### 顺序结构

顺序结构非常简单,实现它都不需要关键字,直接把各个步骤的代码按照从前到后的顺序罗列出来即可。

![eter image decritio here](htt://k.c/6c54c0f0-9319-11e9-9417-f698e8a446d)

***顺序结构***

下面是一个顺序结构的例子:

legth = 10

width = 5

ace = legth * width

rit("Sace i: % quare meter" % ace)

***代码-1***

输出为:

> Sace i: 50 quare meter

套用我们之前学过的代码块的概念,在这段代码里,四行代码都属于同一个代码块,四行代码地位均等:

![eter image decritio here](htt://k.c/dd0-933e-11e9-9417-f698e8a446d)

因此,它们要运行,就一条不差地按从上到下的顺序运行。

#### 条件结构

大多数情况下,条件结构需要用到 2 个关键字:if 和 ele;有时只需要 if 就可以;还有的时候,另需要 elif 关键字。

我们先来看看大多数的情况:

![eter image decritio here](htt://k.c/9ecd2220-9319-11e9-877d-6f1f1c96f1d)

***条件结构***

if 关键字是条件结构必须有的关键字,if 标志了一个控制结构的开始。if 之后是一个空格,然后是条件语句的条件——对应流程图中菱形框内的部分。

> **NOTE**:代码中的条件部分其实不必用括号括起来,图中这么画是为了让你看清楚条件。

if 语句的结尾是一个**冒号**——这个冒号是必须有的,初学者经常会忽视这个冒号,结果导致程序报错却不知道错在哪里,这一点要注意。

在 if 行之下,有一个子代码块,这个代码块的内容对应流程图中 YES 之后的部分。

而 NO 对应的部分,需要用另一个关键字:ele 标识出来,ele 后面只有一个冒号。ele 行下面是原本属于 NO 分支的子代码块。**子代码块**需要***一级缩进***,即后退 4 个空格。

下面是一段示例代码:

if ace > 30:

rit("Thi i a ig room.")

ele:

rit("Thi i a ormal room.")

***代码-2***

> **NOTE**:这段代码实际上延续代码-1 的,在代码-1 中 ace 已经被赋值了,所以此处无须再赋值。

>

> 这里例子里每个子代码块都只有一个语句,如果有多个语句的话,这些语句全部相对于「if」一级缩进,它们互相之间是对齐的。

输出是:

> Thi i a ig room.

从代码块的角度解释,在这段代码里面,if 所在一行和 ele 所在一行仍然属于 Block1,但打印「ig room」的语句和打印「ormal room」的语句就成了 if 语句和 ele 语句的子代码块。结构如下:

![eter image decritio here](htt://k.c/3e6f80d0-9337-11e9-f22-7dc7821)

Block2-1 由 if 语句控制,到了 if 语句时,Pytho 解释器要检查一下变量 ace 的值是否大于 30。如果是,则进入 Block2-1 执行;否则则跳过 Block2-1。

if 语句及其子代码块整个运行过后(无论 Block2-1 是否真的被执行了),ele 语句解释器会检查一下 ace > 30 条件的逆条件,即 ace <= 30,如果符合这个逆条件,则进入 Block2-2,否则跳过 Block2-2。

如果 NO 分支无内容,也可以完全没有 ele 行及其子代码块。例如这样的代码:

if ace > 30:

rit("What a ig room!")

***代码-3***

也就是只有 ace > 30 时才打印,否则就什么都不打印。

----------

如果有超过两种情况要考虑,则可以用 elif 语句,elif 实际上就是「ele if」。比如下面例子:

if ace > 30:

rit("Thi i a ig room.")

elif ace > 10:

rit("Thi i a ormal room.")

ele:

rit("Thi i a mall room.")

***代码-4***

代码-4 的细节如下:

- if 语句:

ace > 30 时输出「Thi i a ig room.」

- elif 语句:

ace > 30 条件不满足的情况下,也就是在 ace <=30 的时候,再检查是否 ace > 10,如果是(也就是 10 < ace <= 30) 的时候,输出"Thi i a ormal room."

- ele 语句:

本语句的隐含条件是前面所有条件所限定的情况的并集的逆。

就是说到了 ele 这条语句,就说名当前 ace 变量的值,对于之前的(1)ace > 30 或者 (2)10 < ace <= 30 这两个条件都不满足。也就是说此时的状况是:ace <= 10,针对这种情况,输出"Thi i a mall room."

#### 循环结构

循环结构对应的关键字是 while 或者 for。

在开始学的时候,我们先关注尽量少的关键字,暂时只用 while 来构造循环。实际上所有用 for 构造的循环都可以用 while 重写。

先来看最简单的情况:

![eter image decritio here](htt://k.c/c-931a-11e9-f22-7dc7821)

***循环结构-1***

循环结构以 while 关键字开始,while 语句格式类似 if 语句,也是 while+空格+循环条件+冒号。

while 行下也是一个子代码块,对应流程图中形成环路的 YES 分支。在 YES 分支完成后,while 对应代码块也就结束了。

如果 NO 分支如果有内容的话,将 NO 分支的部分直接放在 while 所控制的整段代码后面。不必再回退 4 格。

下面是一个例子:

arr = ["ale", "orage", "watermelo"]

i = 0

while i < le(arr):

rit(arr[i])

i = i + 1

rit("No fruit.")

***代码-5***

输出为:

> ale

> orage

> watermelo

> No fruit.

这段代码的代码块结构如下:

![eter image decritio here](htt://k.c/c-9339-11e9-877d-6f1f1c96f1d)

Block2 由 while 语句控制。代码执行到 while 语句时,先判断当时变量 i 的值是否小于 arr Lit 的长度,如果满足条件,则进入 Block2 执行其中的两条代码。

Block2 是 while 循环的循环体。每次 Block2 执行完之后,都要再跳回到 while 语句,判断 while 的循环条件 —— i < le(arr) 是否成立。如果成立,则再进入循环体,否则跳过 Block2,继续后面的 Block1。

一旦 Block2 被跳过,说明循环条件的逆条件已经成立了。比如上面的代码,一旦 i 的值不再符合 i < le(arr),则说明已经是 i >= le(arr) 的情况了。

----------

有的时候循环体中会用到 reak 或 cotiue 关键字,前者用于忽然终止循环跳到循环之外,后者则是跳过当前这轮循环,继续进入下一轮循环。

cotiue 一般影响不大,就是会让循环体少执行一次。但是如果遇到 reak 要注意,在循环体中一旦遇到 reak 语句,就直接跳出,而且不会再回头执行 while 中的条件判断。

这个时候,如果要保持原图中循环条件的 NO 分支在确定循环条件为否的时候执行,就要在 while 循环之后,再加一重判断。用图画出来就是:

![eter image decritio here](htt://k.c/f-933-11e9-877d-6f1f1c96f1d)

***循环结构-2*** (其中「!」符号表示取反的意思)

此种结构的例子:

arr = ["ale", "orage", "watermelo"]

i = 0

while i < le(arr):

rit(arr[i])

if (arr[i] == "orage"):

reak

i = i + 1

if i == le(arr):

rit("No fruit.")

***代码-6***

输出是:

> ale

> orage

#### 不同类型结构的嵌套

不同类型的控制结构是可以嵌套的,比如代码-6 中,其实循环结构的循环体中就已经嵌套了一个条件结构了。

嵌套没有更多的限制,只要注意:

- 每个被嵌入到其他结构中的结构都是一个完整的结构体。

- 可以是简化的

例如:条件结构只有 if,没有 elif,也没有 ele —— 简化的结构体

- 但不能是残缺的

例如:条件结构有 if 和 elif,却没有 ele ——残缺的结构体

- 把每个被嵌入的结构都当作一个语句来对待。

##用 Pytho 实现顺序查找算法

### 代码实现

我们按照刚才学的不同结构类型的代码表达,来实现一下流程图-2 中描述的顺序查找算法。代码如下:

***代码-7***

输出为:

> t i elemet 11

### 流程图和代码的对照

流程图和代码的对应关系如下:

![eter image decritio here](htt://k.c/8e7df740-931f-11e9-9d-69ad1684fc56)

这个算法有两个大块结构:顺序(浅蓝色框内)结构和循环结构(浅灰色框内)。

顺序结构自不必言,循环结构看一下代码的实现:

1. 循环条件放在一个 while 语句里,符合循环条件的 YES 分支是是 while 分支下的子代码块(棕色框内);

2. 棕色框内部,也就是 while 循环的子代码块内,正好又有一个条件分支,这个条件分支的 YES 分支中包含了 reak 语句;

3. 与循环条件相悖的 NO 分支放在 while 语句之后,因为循环体中包含 reak 语句,因此循环条件的 NO 分支要再用一个 if 语句来判断是否当时条件正好和 while 中的条件相反(求反)。

☰目录
科普生男生女原因:了解妊娠医学常识 第1章 生男生女到底能不能控制?怎么控制? - 墨韵小说