欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python学习:条件和循环

程序员文章站 2022-06-24 19:39:59
...

在学习了列表、元祖、字典、集合和字符串等一系列 Python 的基本数据类型后,如何把这一个个基本的数据结构类型串接起来,就需要条件和循环了。

一、条件语句

Python 的条件语句,用法很简单。比如,想要表示 y=|x|这个函数,那么相应的代码便是:

# y = |x|
if x < 0:
    y = -x
else:
    y = x

需要注意的是,在条件语句的末尾必须加上冒号(:),这是 Python 特定的语法规范。

由于 Python 不支持 switch 语句,因此,当存在多个条件判断时,需要用 else if 来实现,这在 Python 中的表达是elif。语法如下:

if condition_1:
    statement_1
elif condition_2:
    statement_2
...
elif condition_i:
    statement_i
else:
    statement_n

整个条件语句是顺序执行的,如果遇到一个条件满足,比如 condition_i 满足时,在执行完 statement_i 后,便会退出整个 if、elif、else 条件语句,而不会继续向下执行。

不过要注意,if 语句是可以单独使用的,但 elif、else 都必须和 if 成对使用。

另外,在进行条件判断时, 不少人喜欢省略判断的条件,比如写成下面这样:

if s: # s is a string
    ...
if l: # l is a list
    ...
if i: # i is an int
    ...
... 

关于省略判断条件的常见用法:
Python学习:条件和循环
不过,切记,在实际写代码时,除了 boolean 类型的数据,条件判断最好是显性的。比如,在判断一个整型数是否为 0 时,我们最好写出判断的条件:

if i != 0:
    ...

而不是只写出变量名:

if i:
    ...

二、循环语句

所谓循环,顾名思义,本质上就是遍历集合中的元素。和其他语言一样,Python 中的循环一般通过 for 循环和 while 循环实现。

比如,有一个列表,需要遍历列表中的所有元素并打印输出,代码如下:

l = [1, 2, 3, 4]
for item in l:
    print(item)

1
2
3
4

其实,Python 中的数据结构只要是可迭代的(iterable),比如列表、集合等等,那么都可以通过下面这种方式遍历:

for item in <iterable>:
    ...

这里需要单独强调一下字典。字典本身只有键是可迭代的,如果我们要遍历它的值或者是键值对,就需要通过其内置的函数 values() 或者 items() 实现。其中,values() 返回字典的值的集合,items() 返回键值对的集合。

d = {'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}
for k in d: # 遍历字典的键
    print(k)

name
dob
gender

for v in d.values(): # 遍历字典的值
    print(v)

jason
2000-01-01
male    

for k, v in d.items(): # 遍历字典的键值对
    print('key: {}, value: {}'.format(k, v))

key: name, value: jason
key: dob, value: 2000-01-01
key: gender, value: male 

通过集合中的索引遍历元素,通常通过 range() 这个函数,拿到索引,再去遍历访问集合中的元素。比如下面的代码,遍历一个列表中的元素,当索引小于 5 时,打印输出:

l = [1, 2, 3, 4, 5, 6, 7]
for index in range(0, len(l)):
    if index < 5:
        print(l[index])  
              
1
2
3
4
5

当我们同时需要索引和元素时,还有一种更简洁的方式,那就是通过 Python 内置的函数 enumerate()。用它来遍历集合,不仅返回每个元素,并且还返回其对应的索引,这样一来,上面的例子就可以写成:

l = [1, 2, 3, 4, 5, 6, 7]
for index, item in enumerate(l):
    if index < 5:
        print(item)  
             
1
2
3
4
5

在循环语句中,我们还常常搭配 continue 和 break 一起使用。所谓 continue,就是让程序跳过当前这层循环,继续执行下面的循环;而 break 则是指完全跳出所在的整个循环体。在循环中适当加入 continue 和 break,往往能使程序更加简洁、易读。

比如,给定两个字典,分别是产品名称到价格的映射,和产品名称到颜色列表的映射。我们要找出价格小于 1000,并且颜色不是红色的所有产品名称和颜色的组合。如果不用 continue,代码应该是下面这样的:

# name_price: 产品名称 (str) 到价格 (int) 的映射字典
# name_color: 产品名字 (str) 到颜色 (list of str) 的映射字典
for name, price in name_price.items():
    if price < 1000:
        if name in name_color:
            for color in name_color[name]:
                if color != 'red':
                    print('name: {}, color: {}'.format(name, color))
        else:
            print('name: {}, color: {}'.format(name, 'None'))

而加入 continue 后,代码显然清晰了很多:

# name_price: 产品名称 (str) 到价格 (int) 的映射字典
# name_color: 产品名字 (str) 到颜色 (list of str) 的映射字典
for name, price in name_price.items():
    if price >= 1000:
        continue
    if name not in name_color:
        print('name: {}, color: {}'.format(name, 'None'))
        continue
    for color in name_color[name]:
        if color == 'red':
            continue
        print('name: {}, color: {}'.format(name, color))

我们可以看到,按照第一个版本的写法,从开始一直到打印输出符合条件的产品名称和颜色,共有 5 层 for 或者 if 的嵌套;但第二个版本加入了 continue 后,只有 3 层嵌套。

对于 while 循环,原理也是一样的。它表示当 condition 满足时,一直重复循环内部的操作,直到 condition 不再满足,就跳出循环体。

while condition:
    ....

很多时候,for 循环和 while 循环可以互相转换,比如要遍历一个列表,我们用 while 循环同样可以完成:

l = [1, 2, 3, 4]
index = 0
while index < len(l):
    print(l[index])
    index += 1

通常来说,如果你只是遍历一个已知的集合,找出满足条件的元素,并进行相应的操作,那么使用 for 循环更加简洁。但如果你需要在满足某个条件前,不停地重复某些操作,并且没有特定的集合需要去遍历,那么一般则会使用 while 循环。

同时需要注意的是,for 循环和 while 循环的效率问题。比如下面的 while 循环:

   i = 0
while i < 1000000:
    i += 1

和等价的 for 循环:

for i in range(0, 1000000):
    pass

要知道,**range() 函数是直接由 C 语言写的,调用它速度非常快。**而 while 循环中的“i += 1”这个操作,得通过 Python 的解释器间接调用底层的 C 语言;并且这个简单的操作,又涉及到了对象的创建和删除(因为 i 是整型,是 immutable,i += 1 相当于 i = new int(i + 1))。所以,显然,for 循环的效率更胜一筹。

注意:如果想在for循环中从一个小数到另一个小数,可用np.arange()
可参考https://blog.csdn.net/weixin_44052055/article/details/108358654

三、条件与循环的复用

在阅读代码的时候,你应该常常会发现,有很多将条件与循环并做一行的操作,例如

expression1 if condition else expression2 for item in iterable

将这个表达式分解开来,其实就等同于下面这样的嵌套结构:

for item in iterable:
    if condition:
        expression1
    else:
        expression2

而如果没有 else 语句,则需要写成:

expression for item in iterable if condition

举个例子,比如我们要绘制 y = 2*|x| + 5 的函数图像,给定集合 x 的数据点,需要计算出 y 的数据集合:

y = [value * 2 + 5 if value > 0 else -value * 2 + 5 for value in x]

再比如我们在处理文件中的字符串时,常常遇到的一个场景:将文件中逐行读取的一个完整语句,按逗号分割单词,去掉首位的空字符,并过滤掉长度小于等于 3 的单词,最后返回由单词组成的列表。这同样可以简洁地表达成一行:

text = ' Today,  is, Sunday'
text_list = [s.strip() for s in text.split(',') if len(s.strip()) > 3]
print(text_list)

['Today', 'Sunday']

当然,这样的复用并不仅仅局限于一个循环。比如,给定两个列表 x、y,要求返回 x、y 中所有元素对组成的元祖,相等情况除外。

[(xx, yy) for xx in x for yy in y if xx != yy]

这样的写法就等价于:

l = []
for xx in x:
    for yy in y:
        if xx != yy:
            l.append((xx, yy))

由两个列表attributes和values,然后针对values中每一组子列表value,输入器和attributes中的键对应后的字典,最后返回字典组成的列表。

attributes = ['name', 'dob', 'gender']
values = [['jason', '2000-01-01', 'male'], 
['mike', '1999-01-01', 'male'],
['nancy', '2001-02-01', 'female']
]

# expected outout:
[{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}, 
{'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'}, 
{'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}]

分行的:

out = []
for value in values:
    result = {}
    for index in range(len(value)):
        result[attributes[index]] = value[index]
    out.append(result)
print(out)

一行的:

out = [{attributes[i]: value[i] for i in range(len(attributes))} for value in values ]
print(out)

使用zip函数的一行的:

[dict(zip(attributes, value)) for value in values]

[{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}, {'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'}, {'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}]

zip函数:接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表。

使用zip创建字典:

key = 'abcde'

value = range(1, 6)

d = dict(zip(key, value))

遍历字典: keys() 、values() 、items():

for key,value in d.items():
    print(key, value)

a 1
b 2
c 3
d 4
e 5
d.items()

dict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])

参考:《Python核心技术与实战》