迭代器,三元表达式,列表推存式,字典生成式,生成器生成式,生成器,递归
1. 迭代器
迭代器:他不是函数,只是一个称呼。
python中一切皆是对象(数据类型)
可迭代对象:含有 .__ iter __方法的数据类型就叫做可迭代对象。
除了数字类型,所有数据类型都是可迭代对象。可迭代的对象:Python内置str、list、tuple、dict、set、file都是可迭代对象。
特点:
- 内置有
__iter__
方法的都叫可迭代的对象。
x = 10 #则不是可迭代对象
可迭代对象位 .__iter__
s = "adc"
s.__iter__()
lt = [1,2,3]
lt.__iter__()
tup = (1,)
tup.__iter__()
se = {1}
se.__iter__()
dic ={"a":1}
dic.__iter__()
fw = open("text","a+",encoding="utf-8")
fw.seek(0,0)
fw.__iter__()
# 除了数字类型,所有数据类型都是可迭代对象
迭代器对象
迭代器对象:含有 .__ iter __ 和 .__ next __方法的对象就是迭代器对象。
概念:可迭代的对象执行__iter__
方法得到的返回值。并且可迭代对象会有一个__next__
方法。
只有字符串和列表都是依赖索引取值的,而其他的可迭代对象都是无法依赖索引取值的。因此我们得找到一个方法能让其他的可迭代对象不依赖索引取值。
s = "adc"
s_iter = s.__iter__()
print(s_iter.__iter__()) #不依赖索引取值
print(s[0]) #索引取值
print(s_iter.__iter__())
print(s[1])
print(s_iter.__iter__())
print(s[2])
为什么要有迭代器对象:提供了 不依赖索引取值的手段
dic = {'a': 1, 'b': 2, 'c': 3}
dic_iter = dic.__iter__()
print(dic_iter.__next__()) # 迭代取值 --》 基于上一个值
print(dic_iter.__next__())
print(dic_iter.__next__()) #取不到则报错
为什么要有迭代器对象:提供了 不依赖索引取值的 手段
dic = {'a': 1, 'b': 2, 'c': 3}
dic_iter = dic.__iter__()
print(dic_iter.__next__()) #a
print(dic_iter.__next__()) #b
print(dic_iter.__next__()) #c
print(dic_iter.__next__()) #取不到则报错
对上面迭代问题,我们使用while循环精简 使用try: escept stopiteration:的异常处理模块
模板
dic_iter = dic.__iter__()
while True:
try:
print(dic_iter.__next__())
except StopIteration:
break
列题:
s = 'hello'
iter_s = s.__iter__()
while True:
try:
print(iter_s.__next__())
except StopIteration: #除了迭代对象(hello)停止迭代运行 h e l l o
break
总结
迭代器对象:执行可迭代对象的__iter__
方法,拿到的返回值就是迭代器对象。
特点:
- 内置
__next__
方法,执行该方法会拿到迭代器对象中的一个值 - 内置有
__iter__
方法,执行该方法会拿到迭代器本身 - 文件本身就是迭代器对象。
缺点:
- 取值麻烦,只能一个一个取,并且只能往后取,值取了就没了
- 无法使用len()方法获取长度
for循环原理
for循环原理:(for循环本质就是一个while循环,只不过是一个一定可控的while循环)
for循环称为迭代器循环,in后必须是可迭代的对象
list = [1,2,3,4]
for i in liast:
print(i) # 1,2,3,4
牢记:
可迭代对象: 含有__ iter __ 方法叫做可迭代对象 --> 除了数字类型都是可迭代对象 --> 可迭代对象使用 __ iter __变成迭代器
迭代器对象: 含有__ iter __ 和 __ next __ 方法叫做迭代器对象 --> 只有文件时迭代器对象 --> 迭代器使用 __ iter __依然是迭代 器
可迭代对象不一定是迭代器对象; 迭代器对象一定是可迭代对象
2.三元表达式
条件成立时的返回值 if 条件 else 条件不成立时的返回值
通常用:
x = 10
y = 20
if x > y:
print(x)
else:
print(y) #20
三元表达式:
x = 10
y = 20
print(f"x if x > y else y: {x if x > y else y}") #x if x > y else y: 20
3.列表推存式
lt = []
for i in range(10):
lt.append(i)
lt = [i**2 for i in range(10)]
print(lt) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
from typing import Iterable #导出一个可迭代对象类型。
print(isinstance(range(10),Iterable)) #判断是否属于该数据类型。
4.字典生成式
dic = {}
for i in range(10):
dic[i] = i
print(dic) # 0:0 1:1...9:9
dic = {i:i**2 for i in range(10)}
print(dic) # 0:0 1:1 2:4.....9:81
zip (解压缩)
res = zip([1,2,3],[4,5,3,2,2],"qwer") ## res是一个迭代器,__next__返回元组
print(res.__next__()) #(1, 4, 'q')
print(res.__next__()) #(2, 5, 'w')
print(res.__next__()) #(3, 3, 'e')
print(res.__next__()) #报错 #则列表中的数取完,则报错。
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}
lt = list("abc")
print(lt) # ['a','b',"c"]
5.生成器生成式
generator 本质是一个迭代器 --> 生成器:本质就是迭代器,生成器就是一个自定义的迭代器。
# 生成器表达式: 看成老母鸡,节省内存空间,用就下蛋
g = (i for i in range(10000))
print(g)
for i in g:
print(i)
# 列表推导式: 看成一筐鸡蛋,非常占用内存空间
lt = [i for i in range(10000)]
print(lt)
6.生成器
generator 本质是一个迭代器 --> 生成器:本质就是迭代器,生成器就是一个自定义的迭代器。
生成器:含有yield关键字的函数叫生成器
def ge(): #1 #3 #6
yield 3 #7 #9
yield 4 #10
print(ge()) #2 ge()得到一个生成器 --> 生成器本质是迭代器 <str_iterator object at 0x00000293FE9BE148> 列print(s_iter.__iter__())。。。
g=ge() #4 得到一个生成器
print(g.__next__()) #5
print(g.__next__()) #8 print--> 3,4
#for i in g:
# print(i) #简化上面两个打印值
6.1 特征
# yield的特性
# 1. 暂停函数
# 2. 通过next取值
# return的特性
# 1. 终止函数
# 2. 通过调用函数拿到值
迭代器套迭代器
ef sub_generator():
yield 1
yield 2
for i in range(3):
yield i
for i in sub_generator():
print(i) # 1 2 0 1 2
def range(start)
count = 0
while count <start:
yield count
count += 1
for i in range(10)
print(i)
7.递归
递归:表示回归。
递归:函数a内部直接调用函数a本身
import sys
sys.setrecursionlimit(10)
print(sys.getrecursionlimit()) #10
def a():
x = 1
print(x)
a() #函数a内部直接调用函数a本身
a()
#每一次递归,会不会结束函数?不会,并且每一次递归都会开辟内存空间,如果一直开辟内存就炸掉了,所以最多递归1000次
真正递归必须得有退出条件。
count = 0
def a():
global count
count +=1
print(count)
if count == 5:
return
a()
a() #1,2,3,4,5
递归的特点
1.函数内部调用函数自己
2.必须要有推出条件
3.递归必需要有规律。
列题:
玉阳 20岁 ; 后面的同学大2岁,后面的后面的同学比后面的同学大2岁; 求第6位同学的年龄
''' #规律
20
20 + 2
20 + 2 + 2
20 + 2 + 2
'''
def age(x):
if x == 0:
return 18
x -= 1
return age(x) + 2
res = age(6)
print(res) # 32
'''
res = 30
res = 28 + 2
res = 26 + 2 + 2
res = 24 + 2 + 2 + 2
res = 22 + 2 + 2 + 2 + 2
res = 20 + 2 + 2 + 2 + 2 + 2
res = 18 + 2 + 2 + 2 + 2 + 2 + 2