Python 学习笔记(05)条件&循环

Python 学习笔记(05)条件&循环

5.1 条件语句

if语句由 关键字本身(if)+ 条件表达式 + 代码块组成,多重条件包括【and/or/not】三种。

if判断为True的情况也有很多种,例如非零数值、非空字符串、非空列表等。单一语句代码块可以放在同一行。

if cond_1_expr:
    ...
elif cond_2_expr:
	...
elif cond_3_expr:
	...
else:
    print("This should be the last condition")
    
# 条件表达式(三元操作符)
smaller = x if x < y else y 

5.2 循环语句

5.2.1 while 条件循环

while condition() != True:
    ...
<else: ...>
    
"""
for...else...和 while...else...中else子句只在【循环正常完成后】执行,如果循环由于循环体中break语句退出则不会执行else子句,因此可以使用其测试循环是否正常结束。
"""

5.2.2 for 迭代循环

for循环原理为遍历所有成员,依次访问可迭代对象(序列、迭代器等)。

1)for循环遍历字符串、列表、元组等序列类型时,可以通过序列项、序列索引或通过**enumerate()**函数建立【索引&项】元组的形式进行迭代,其中直接迭代序列比通过索引的方式更快;

2)for循环遍历迭代器时,自动调用迭代器对象 **next()**方法,调用后返回【下一个条目】,直到捕获 StopIteration异常时结束循环。

list_1 = ['list', 'tuple', 'dict', 'set']

# 1)直接迭代序列
for item in list_1:
    print(item)
    
# 2)通过序列索引迭代
for i in range(len(list_1)):
    print(list_1[i])
    
# 3)通过enumerate()函数迭代
for i, value in enumerate(list_1):
    print(i, value)

5.2.3 循环控制

1)break

停止执行整个循环,直接跳出。

2)continue

跳过本次执行,进入下一次循环。在条件循环中,需要验证条件表达式;在迭代循环中,需要验证是否还有可迭代的元素。满足条件后才会进行continue。

3)pass

代表空语句,主要作用为在开发、调试过程中用来先确定结构,或是在异常处理中暂时不采取任何措施。

pass不仅可以在循环中使用,可以出现在任何需要【语句块】的地方。

5.3 相关内建函数(BIF)

range(start, end, step)		range(end)		range(start, end)

"""
用于创建一个循环范围,可以结合len()实现【下标】控制循环。
"""

enumerate()				# 每次循环返回tuple(索引-元素对)

reversed()				# 逆序访问

zipped = zip(seq_1, seq_2, ...)

"""
用于聚合列表,从多个等长序列中依次取出一个元素组成【元组】;
相对应的接触聚合 seq_1, seq_2 = zip(*zipped)
"""

sorted(iterable, key=None, reverse=False)  

"""
iterable 表示指定的序列,key 参数可以自定义排序规则;reverse 参数指定以升序(False,默认)还是降序(True)进行排序。sorted() 函数会返回一个排好序的列表。
"""

5.4 迭代器

迭代是python中访问集合元素的一种循环方式,迭代器是一个可以记住遍历位置的对象,其主要目的是为【类序列对象】提供类序列接口,例如字典的键、文件的行等,用于迭代不是序列但表现出序列行为的对象。

如何判断是否对象是否可迭代?

from collections import Iterable

isinstance(class, Iterable)

"""
可迭代对象都含有__iter__方法,只要通过isinstance()和Iterable检查自定义类创建的实例对象即可。
"""

5.4.1 迭代对象 可迭代对象

迭代对象是指实现了__iter__与 next() 方法的对象;

可迭代对象可以只实现__iter__,也可以两个都实现,有些可迭代对象的迭代对象就是它本身。如果一个可迭代对象同时是它的迭代对象,则无法重复迭代。

# 使用iter()可以获取一个可迭代对象的迭代对象
iter(obj)			# obj = str/list/tuple

# 判断可迭代对象的迭代对象是不是它本身
print(iter(obj) is obj)

迭代器的本质并非【索引计数】,而是使用 next() 函数。迭代器自动调用迭代器对象 next()方法,调用后返回下一个条目,直到捕获StopIteration异常后结束循环。

5.4.2 迭代器的使用

import sys

# for循环
fetch = iter(seq)

for i in fetch:						# 通过循环访问迭代器
    do_something_to(i)
    
while True:							# 通过next()访问迭代器
    try:
        next(fetch)
    except	StopIteration:
        sys.exit()
        
 # 字典
dict_1.keys()	dict_1.values()	  dict_1.items()

# 文件
readline()							# for eachline in open('*.txt')

5.4.3 迭代器注意事项

1)对于【可变对象】,迭代时不允许添加、删除元素

对于列表,迭代器记录的是当前到达第几个元素,改变列表更新会立刻反应到【迭代条目】上,会引发迭代混乱问题;

对于字典,修改会引发错误,切记不可改变字典。

2)迭代器限制

迭代器的移动方向只能向后,不可回到开始;

迭代器无法复制,只能创建另一个迭代器。

5.5 列表解析

列表解析放在方括号中,因为最后构建出来的是一个新的列表(python 3.X可以用解析构造元组、字典)。

# 常规方式修改列表
for i in range(len(list_1)):
    list_1[i] += 10
    
# 列表解析基本语法
list_1 = [x + 10 for x in list_1]							# [expr for iter_var in iterable]

# 列表解析拓展语法
[expr for iter_var in iterable if cond_expr]

# 双层循环形成全排列
file_1 = open('*.txt')
print([word for line in file_1 for word in line.spilt()])	# [expr(a, b) for a in iter_1 for b in iter_2]

# 同时使用dict的键、值
dict_1 = {'key': 'value'}
print([key for key, value in dict_1.items()])

# 与zip结合使用
print([x**2 for (x, y) in zip(seq_1, seq_2) if y > 10])

5.6 生成器

生成器可以理解为生成数据的工具,按照某种规则不断的生成数据直至结束。

从形式上生成器仅仅是将列表解析式的方括号换成了圆括号,实际使用上生成器和列表解析式有很大的差别。列表解析需要一次生成所有数据,若列表元素过多则会占据很大的内存空间;而生成器可以看作列表解析和迭代器的结合,在循环中一边循环一边计算后续元素,一次仅生成一个元素,即优化了内存使用又可以获取完整的列表内容。

5.6.1 生成器表达式

list_1 = [x**2 for x in range(1, 20) if x % 2 == 0]

# 创建生成器
generator_1 = (x**2 for x in range(1, 20) if x % 2 == 0)

print(type(list_1))
print("list_1: ", list_1)
print(type(generator_1))
print("generator_1: ", generator_1)

Out:
<class 'list'>
list_1:  [4, 16, 36, 64, 100, 144, 196, 256, 324]
<class 'generator'>
generator_1:  <generator object <genexpr> at 0x000001F3817036D0>
    
"""
可以看到,使用列表解析式即生成了一个完整的列表,包含了列表所有元素;而使用生成器产生的不包含任何元素。
"""

# 获取生成器中的值
print(next(generator_1), '\n')		# generator_1.__next__()

# 生成器循环元素
for i in generator_1:
    print(i)

Out:
4

16
36
64
100
144
196
256
324

"""
当对生成器进行迭代时,可以获取生成器生成的整个列表的元素,但生成器只能迭代一次,完成后将无法获取内容。
由于代码中先使用next方法取出了一个生成器中的数,后面 for循环中迭代并不包含这个值。
生成器的内涵在于 允许返回一个值同时“暂停”代码的运行,需要时再“恢复”运行。
"""

5.6.2 yield关键字实现生成器

# 创建生成器
def generate(start, end):
    for n in range(start, end):
        if n % 2 == 0:
            yield n**2
        
"""
原本def用法是定义函数,但当函数体中 return 被替换为 yield 后,便可以用作定义生成器;
yield可以看作和 return功能近似即返回;函数体内可以定义多个yield;
yield实现的生成器可以使用for循环和next()进行迭代。
"""

items = generate(1, 20)

for i in items:
    print(i)

Out:
4
16
36
64
100
144
196
256
324
# yield 详细解释
def func():
    print("starting...")
    while True:
        res = yield 1
        print("res: ", res)

generator_1 = func()
print(next(generator_1))
print("~"*20)
print(next(generator_1))
print("~"*20)
print(generator_1.send(-1))

Out:
starting...
1
~~~~~~~~~~~~~~~~~~~~
res: None
1
~~~~~~~~~~~~~~~~~~~~
res: -1
1

"""
1.程序开始运行后,因为fun()中含有关键字yield,所以调用时得到一个生成器对象generator_1;
2.当调用next(generator_1)方法时,fun()函数开始执行,先执行函数体中print方法,再进入while循环;
3.程序遇到yield关键字,将其视为return,此时执行第一个print(next(generator_1))输出1,之后函数暂停;
4.注意:函数暂停时并没有执行赋值给res的操作,第一条next(generator_1)结束;
5.print("~"*20);
6.开始执行第二条next(generator_1),继续刚才还未赋值的状态。但此时由于yield将值返回到了主程序中,导致赋值右边没有值可赋,此时为None。所以接下来输出的就是res: None;
7.程序继续运行,第二次碰到yield,此时执行第二个print(next(generator_1))输出1,之后函数暂停;
8.print("~"*20);
9.send()函数作用在于传递一个值给res,注意第二次暂停还是停在赋值操作。由于send()将值赋给了res,因此输出res: -1;
10.由于send()函数中包含next()方法,所以程序会继续向下运行,直到第三次碰到yield,print(generator_1.send(-1))输出1后停止。
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值