解决场景问题

解决场景问题

现在我们来看一个具体场景下的 Python 代码编写。

在上一章节中,我们编写了一段这样的代码:

1
2
3
name = input("请输入你的姓名:")
age = input("请输入你的年龄:")
print("你好,%s 岁的%s!" % (age, name))

执行这段代码时,程序将获取我们输入的名字和岁数,并且按照某种形式打印出来。

场景问题

假设,现在有这么一种场景:某娱乐场所的前台登记系统,需要用户输入自己的姓名和年龄,系统将判断用户是否成年,如果成年则欢迎并放行,否则让用户回家。我们该如何用 Python 来实现这个需求呢?

条件语句

很显然,我们需要对用户输入的年龄进行判断,这就要有请判断语句:ifelse 出场了

1
2
3
4
5
6
age = 10

if age >= 18: # 当 age 大于等于 18 时
print("成年")
else: # 其它情况时
print("未成年")

# 表示注释,Python 中只有单行注释,即与 # 在同一行并在它后面的都是注释,程序在执行时将忽略掉注释,注释的存在是便于程序的编写者和阅读者理解代码的含义与用途。

上面的代码将判断 age 变量的值是否大于等于 18,如果是则打印“成年”,否则打印“未成年”,不要漏掉那个冒号 :

Python 的一大特点是用缩进表示语句块,建议使用四个空格缩进而不是按 tab 键,出于方便,我们可以把 tab 替换成四个空格:

img

通常情况下这就是默认配置

现在我们再利用判断语句将之前的代码改进一下:

1
2
3
4
5
6
7
name = input("请输入你的姓名:")
age = int(input("请输入你的年龄:"))

if age >= 18:
print("欢迎您的到来,里面请!")
else:
print("小孩子回家玩去")

之所以 input("请输入你的年龄:")int() 包裹,是因为 input() 在这里实际上是获取到一个字符串,所以用 int() 强制转换为数字,方便我们下面的判断。我们测试一下:

1
2
3
4
5
6
7
> 输入你的姓名:谭小蝶
> 请输入你的年龄:18
欢迎您的到来,里面请!
=============================
> 输入你的姓名:莉莉
> 请输入你的年龄:8
小孩子回家玩去

可以看到成功了,非常棒。如果这个时候,又有新需求,考虑到身体健康问题,大于 60 岁的用户就不再放行。我们可以改写成这样:

1
2
3
4
5
6
7
8
9
name = input("请输入你的姓名:")
age = int(input("请输入你的年龄:"))

if age > 60: # 当 age 大于 60 时
print("大爷先回家歇歇吧!")
elif age >= 18: # 当 age 小于等于 60 并且 大于等于 18 时
print("欢迎您的到来,里面请!")
else: # 其余情况
print("小孩子回家玩去")

elifelse if 的简写,顾名思义,表示“否则,如果……”,程序会自上而下的依次判断是否符合条件,如果遇到条件符合时,将执行相应的语句,并不再判断接下来的条件,所以先判断的条件要放到更上面。

1
2
3
4
5
6
7
8
9
10
11
> 输入你的姓名:谭小蝶
> 请输入你的年龄:18
欢迎您的到来,里面请!
=============================
> 输入你的姓名:莉莉
> 请输入你的年龄:8
小孩子回家玩去
=============================
> 输入你的姓名:王大爷
> 请输入你的年龄:80
大爷先回家歇歇吧!

测试了一下,符合我们的预期,非常棒哈。

但是,在程序就有非常有名的一句话: 永远不要相信用户的输入 ,万一上面的这个登记系统,用户傻傻的把名字和年龄填反了怎么办?如果遇见捣蛋鬼存心乱填怎么办?

1
2
3
4
> 请输入你的年龄: 莉莉
> 请输入你的年龄: 二十八岁
> 请输入你的年龄: 不便透露
> 请输入你的年龄: bilibili

合法性验证

事实上,仅凭之前的代码,根本无法应对这些情况,所以,我们需要对用户的输入合法性(合理性)也进行判断,改进后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
name = input("请输入你的姓名:")
age = input("请输入你的年龄:")

if age.isdigit(): # 当 age 由纯数字构成时
age = int(age)
if age > 60: # 当 age 大于 60 时
print("大爷先回家歇歇吧!")
elif age >= 18: # 当 age 小于等于 60 并且 大于等于 18 时
print("欢迎您的到来,里面请!")
else: # 其余情况
print("小孩子回家玩去")
else:
print("你丫的输入了个啥?")

我们对新代码逐一分析,首先在第二行中,我们去掉了 int() ,因为在这里我们还无法判断用户输入的是否为纯数字,如果不是纯数字却执行 int() 可能会报错。

虽然用户也有可能输入诸如 -10 或者 2333 这种显然不可能存在的岁数,不过程序不会报错,而且反正也通不过我们原有的判断,所以暂时不做处理。

age.isdigit() 用于获取是否 age 是否为纯数字,如果是返回 True,否者返回 FalseTrueFalse 都属于“布尔值(Boolean)“数据类型,用于表示真假;理解了布尔值的概念后,我们回过头再去看看 if

1
2
3
4
5
6
7
8
9
10
11
age = "18"
if (age.isdigit()): print("执行啦")
if (5 > 4): print("执行啦")
if True: print("执行啦")
# 以上都为真,都会执行冒号后面的语句

name = "王小二"
if (name.isdigit()): print("我永远不会被调用,哭唧唧")
if (4 > 5): print("我永远不会被调用,哭唧唧")
if False: print("我永远不会被调用,哭唧唧")
# 以上都为假,都看不到它们哭唧唧

实际上,if: 之间的语句被程序判断,返回一个布尔值,最终等价于 if True:if False,前者会执行之后的语句。

另外,在计算机中我们常常用 1 表示”真“,0 表示 ”假“,所以 True 也等于 1,相应的 False 也等于 0

1
2
3
4
>>> True == 1
True
>>> False == 0
True

正如你所注意的,在代码中通常用两个等号 == 表示通常意义上的”相等“,这是避免和一个等号 = 表示的赋值相冲突。

回到之前的前台登记需求,现在我们已经能安全的判断用户输入的年龄,符合我们准入规则的才放行。现在,又有新情况:老板 40 岁生日,他大手一挥,宣布今天跟他同岁的顾客统统免单,并且他年仅 8 岁的小女儿莉莉也允许进入。

还能咋办?有需求咱就改呗:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
name = input("请输入你的姓名:")
age = input("请输入你的年龄:")

if age.isdigit(): # 当 age 由纯数字构成时
age = int(age)
if name == "莉莉":
print("小姐里面请!")
elif age > 60: # 当 age 大于 60 时
print("大爷先回家歇歇吧!")
elif age == 40:
print("贡献您,今日消费全免,里面请!")
elif age >= 18: # 当 age 小于等于 60 并且 大于等于 18 时
print("欢迎您的到来,里面请!")
else: # 其余情况
print("小孩子回家玩去")
else:
print("你丫的输入了个啥?")

由于 if……elif……else…… 自上而下判断,所以我们需要根据情况合理的调整判断顺序,然后测试一下:

1
2
3
4
5
6
7
> 请输入你的姓名:莉莉
> 请输入你的年龄:8
小姐里面请!
=============================
> 请输入你的姓名:葛蛋蛋
> 请输入你的年龄:40
恭喜您,今日消费全面,里面请!

非常好,实现了需求。

更多的思考

老板满意的看着你,表示你可以下班回家休息了。你心满意足的回到家,洗澡的时候脑子里突然冒出了今天写的代码,你突然觉得大段的 if……elif……else…… 看起来啰嗦累赘,还一不小心没理清逻辑就写错条件。

继而你接着想到,给用户输入的机会只有一次,要是用户一不小心输错了,就直接被拒之门外了,这样的用户体验也不好。并且如果有人输小姐的名字假冒她,也被直接放进来了,这显然不行;再者,直接让用户输年龄,不排除有人谎报的,应该用更严谨的方式确定年龄。

该怎么改进上面的问题呢,将在下一章娓娓道来。