迭代器
可迭代对象
可迭代对象:可迭代的对象,内置有__iter__方法的对象都是可迭代对象,除了数字类型,所有数据类型都是可迭代对象。
Python内置str、list、tuple、dict、set、file都是可迭代对象
迭代器对象
迭代器对象:执行可迭代对象的__iter__方法,执行该方法会拿到返回值,这个返回值就是可迭代对象。
为什么要有迭代器对象:提供了一种不依赖索引取值的手段。
特点:
- 内置__next__方法,执行该方法会拿到迭代器对象中的一个值。
- 内置__iter__方法,执行该方法会拿到迭代器本身。
- 文件本身就是迭代器对象。
缺点:
-
取值麻烦,只能一个一个取,并且只能往后取,值取了就没了。
-
无法使用len()方法获取长度。
s = 'hello' iter_s = s.__iter__() while True: try: print(iter_s.__next__()) except StopIteration: break
h
e
l
l
o
for循环原理
for循环称为迭代器循环,in后必须是可迭代的对象。
def for1(iterable):
iterable = iterable.__iter__()
while True:
try:
print(iterable.__next__())
except StopIteration:
break
for1([1,2,3,4])
1
2
3
4
三元表达式
# x = 10
# y = 20
# if x > y:
# print(x)
# else:
# print(y)
print(x) if x > y else print(y)
#条件成立走这里 if 条件 else 条件不成立走这里
列表推到式
# lt = []
#
# for i in range(10):
# lt.append(i)
lt = [i**2 for i in range(10)]#此处可对i进行取幂等运算
# from typing import Iterable # 导出一个可迭代对象类型
#
# print(isinstance(range(10),Iterable)) # 判断是否属于该数据类型
字典生成式
print({i: i**2 for i in range(10)})
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
zip()方法
描述
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip 方法在 Python 2 和 Python 3 中的不同:在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。如需展示列表,需手动 list() 转换。
如果需要了解 Pyhton3 的应用,可以参考 Python3 zip()。
语法
zip 语法:
zip([iterable, ...])
参数说明:
- iterabl -- 一个或多个迭代器;
返回值
返回元组列表。
res = zip([1,2,3],[4,2,3,4,2,3,4,2,3],'abcadsfasdfasdf') # res是一个迭代器,__next__返回元组
print(res.__next__()) # type:tuple
print(res.__next__()) # type:tuple
print(res.__next__()) # type:tuple
(1, 4, 'a')
(2, 2, 'b')
(3, 3, 'c')
利用zip()方法生成字典
lt1 = ['a','b','c']
lt2 = [1,2,3]
dic = {k:v**2 for k,v in zip(lt1,lt2)}
print(dic)
{'a': 1, 'b': 4, 'c': 9}
生成器
generator本质是一个迭代器——》生成器:本质就是迭代器,是一个自定义的迭代器。
g = (i for i in range(10))#生成器表达式
print(g)
for i in g:
print(i)
#列表推导式相当于直接给你一筐蛋,而生成器表达式相当于给你一只老母鸡。
lt = [i for i in range(10)]#列表生成式
print(lt)
<generator object
0
1
2
3
4
5
6
7
8
9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 把列表推导式的[]换成()就是生成器表达式
- 优点:省内存,一次只产生一个值在内存中
生成器
含有yield关键字的函数叫做生成器
def ge():
yield 3 # 一个yield相当于一个next; 暂停函数
yield 4
yield 5
# print(ge()) # ge()得到一个生成器 --> 生成器本质是迭代器
g = ge() # 得到一个生成器
print(g.__next__())#一个yield只能迭代一次
print(g.__next__())
#print(g.__next__())
#for i in g:
# print(i)#一个一个迭代,如果next没有迭代完就继续迭代,如果next已经将yield迭代完就停止迭代输出
3未注释掉最后两行时
4
5
注释掉最后两行时
3
4
yield:
- 提供一种自定义迭代器的方式
- yield可以暂停住函数,并提供当前的返回值
yield和return:
- 相同点:两者都是在函数内部使用,都可以返回值,并且返回值没有类型和个数的限制
- 不同点:return只能返回一次之;yield可以返回多次值
生成器表达式
-
把列表推导式的[]换成()就是生成器表达式
-
优点:省内存,一次只产生一个值在内存中
关于为啥节省内存参考下面链接,个人认为,生成器利用迭代关系取值,每次只有一个值进入内存,所以节省内存空间,而列表则是把所有的元素全都放在内存里所以比较占内存。
https://www.runoob.com/w3cnote/python-yield-used-analysis.html
递归
一、直接调用
递归:在函数a内部直接调用函数a本身,递归必须要有退出条件。
写递归程序的方法:先写循环再替换成递归
def a():
global count
count += 1
print(count)
if count == 5
return
a()
a()
特点:
- 函数内部调用函数自己
- 必须要有退出条件
- 必须要有规律
二、间接调用
间接调用指的是:不是在原函数体内调用函数自身,而是通过其他的方法间接调用函数自身。
def bar():
print('from bar')
foo()
def foo():
print('from foo')
bar()
bar()
递归必须要有两个明确的阶段:
- 递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小
- 速回:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯
- 递归的精髓在于不断的重复逼近一个最终的结果
'''
...
age(5) = age(4) + 2
age(4) = age(3) + 2
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 26
age(n) = age(n-1) +2
age(1) = 26 # n=1
'''
def age(n):
if n == 1:
return 26
res = age(n-1) + 2
return res
print(f"age(5): {age(5)}")
#age(5): 34
递归的使用:二分法查找数据参考Nick的博客