Python中的三元表达式/and和or的执行原理/True和False的本质/列表生成式/生成器

一看标题,看似是三个不相关的问题,实际上息息相关。

我们都知道,“C系语言(C\C++、C#、Java等)”都有一个共同的知识点:三目运算符,其主要作用还是为了简化选择结构语句。让其不是那么冗杂,繁多,具体用法如下:

C语言:

#include<stdio.h>

int main()
{

int a = 2;
int b = 3;

if(a > b)

    int c = a;

else

    c = b;

return 0;

}

使用三目运算符便可以这样简化以上语句:

#include<stdio.h>

int main()
{

int a = 2;
int b = 3;

c = a > b?a:b;

return 0;

}

标识符=条件表达式?表达式1:表达式2?表达式3:表达式4

 

但是Python显得与“C系语言”格格不入,Python没有三目运算符,但是Python有一个东西,它与三目运算符的功能类似,我们称其为“三元表达式”。

用法如下:

a, b, c = 1, 2, 3

if a>b:

    c = a

else:

    c = b

可以简写为:

c = a if a>b else b

可以看到,Python的三元表达式与三目运算符的功能极其类似。可能Python开发者这样编写Python的原因就是为了增强可读性,因为运算符的长相毕竟很不友好,里面既有冒号还有问号,不知情的初学者会一脸懵逼。而换成我们熟知的if、else便会对初学者友好许多。

但实际上,想要简化代码,方法有很多。只要脑洞大,什么方法都是好方法。比如,我们可以用列表来模仿三元表达式:

c = [b, a][a > b]

还可以用经典的and、or操作符来模仿三元表达式:

c = (a>b and [a] or [b])[0]
# 改编版
c = (a>b and a or b)

这里有的读者可能不理解这里的代码,这里做出如下解释:

可以使用and和or的原因是:and和or在本质上就是个if...else语句,也就可以是三元表达式。

我们一提到and,就想到是在做逻辑运算:如下:

#0 and 1的结果是0(有零则零)

#1 and 1的结果是1(全一才一)

#0 or 1的结果的1(有一则一)

#0 or 0的结果是0(全零才零)

那为什么会是这样的结果呢?

因为and和or在本质上就是if...else语句。

表达式exp1 and exp2等价于:

if not exp1:
    return exp1
else:
    return exp2

那就当然可以写成:

exp1 if not exp1 else exp2

=====================================================

同理,对于or:

表达式exp1 or exp2等价于:

if exp1:
    return exp1
else:
    return exp2

那就当然可以写成:

exp1 if exp1 else exp2

知道了这个,就好理解and和or的本质了:

为什么 0 and 1 的结果为0呢?很简单:

if not 0:
    return 0
else:
    return 1

一看便知,结果是0。

为什么 0 or 1 的结果为1呢?很简单:

if  0:
    return 0
else:
    return 1

一看便知,结果是1。

其余情况读者可以自行尝试。

这样,如果and和or的操作数不是0或1,而是其他的数,我们也好办了。

这就引出是我们讨论的第三个问题:Python中True和False的本质。

我用经典的IPO程序设计方法(输入、处理、输出)来概括:

当True和False被用作了输入,处理的过程需要我们把他们当做整数类型来运算,那么True和False的输出分别为1和0;

当True和False被用作了输出,处理的过程需要我们把他们当做布尔类型来运算,那么True的输入可以是除零以外的任何整数值,False的输入只能是0;

现在,我举以下例子或题目帮助读者理解这两句话:

全国计算机等级考试——Python语言程序设计有这么一道例题:

给出如下代码:

import turtle
def drawLine(draw):
    turtle.pendown() if draw else turtle.penup()
    turtle.fd(50)
    turtle.right(90)

drawLine(True)
drawLine(True)
drawLine(True)
drawLine(True)

以下选项中描述错误的是

A.运行代码,在Python Turtle Graphics中,绘制一个正方形

B.代码 drawLine(draw)可取值为True或者False

C.代码drawLine(True)中的True替换为-1,运行代码结果不变

D.代码drawLine(True)中的True替换为0,运行代码结果不变

这道题的答案很直白,即使考生不会这道题,只要使用选择题题型独有的做题技巧(大家中学时期做过这么多的选择题,这里就不在赘述了,大家都懂),也可以把这道题的答案蒙出来,为D选项。

下面具体解释这道题:

除了if...else,Python还可以把for循环当做三元表达式用来快速生成列表:

L=[]
for x in range(1,11):
    L.append(x*x)
print(L)

写这样的循环无疑是繁琐的,所以,以上代码可以等价于:

L = [x*x for x in range(1,11)]

这就是传说中的列表生成式。

我们都知道,for循环不仅仅有一层的,还有两层的for循环。

比如说:

for m in 'AB':
    for n in 'CD':
        L.append(m + n)

print(L)

相当于: 

L = [m + n for m in 'AB' for n in 'CD']
print(L)

简洁了不止一星半点。

结果为:['AC','AD','BC','BD']。

当然了,还可以套三层或三层以上的for循环,不过很少用到,这里也不进行赘述。

我们还可以试试与if...else结合:

L = [x*x for x in range(1,11) if x%2==0]
#找到从1到10所有的偶数的平方项

看到这里,有的同学可能会这样的问题,中括号里的“x*x for x in range(1,11) if x%2==0”到底是个什么东西?

如果“x*x for x in range(1,11) if x%2==0”单独存在的话,被Python解释器认为的错误的语法。所以,它不是个东西!

但如果这个东西外面加了圆括号,那他就是传说中的“生成器”。

还是,全国计算机等级考试——Python语言程序设计有这么一道例题:

下面代码的输入结果是:

L = [1,2,3,4,5]
s1 = ','.join(str(n) for n in L)
print(s1)

A. [1,2,3,4,5]    B. 1,2,3,4,5

C.[1,,2,,3,,4,,5]  D.1,,2,,3,,4,,5 

解析:如果考生不了解这道题join(str(n) for n in L)里面的str(n) for n in L是个什么东西,但是知道join内置函数的作用,这道题的答案也呼之欲出。首先,join函数返回的是字符串类型,故排除A、C选项。其次,观察join(str(n) for n in L)的内容,可以猜出:是把L的元素依次转化为字符串,故选B。

 

 

参考文献:

https://www.cnblogs.com/chenmh/p/5750726.html

https://www.cnblogs.com/xiexiaoxiao/p/7772441.html

https://www.cnblogs.com/wanghao123/p/7921654.html(还未使用)

《高教版Python语言程序设计冲刺试卷(含线上题库)》黄天羽 李芬芬/著 高等教育出版社

《玩转Python,轻松过二级》·董付国/著 清华大学出版社

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值