python基础--迭代器、生成器、递归
迭代器
迭代器:不是函数,只是一个称呼而已
python中一切皆对象(数据类型)
可迭代对象:含有.__iter__方法的数据类型就叫做可迭代对象
name = 'allen'.__iter__()
lis = [1,2,3,4]
iter_lis = lis.__iter__()
dic = {'a':1,'b':2,'c':3}
iter_dic = dic.__iter__()
除了数字类型,所有数据类型都是可迭代对象
迭代器对象: 含有__iter__和__next__方法的对象就是迭代器对象
name = 'allen'.__iter__()
print(name.__next__())
lis = [1,2,3,4]
iter_lis = lis.__iter__()
print(iter_lis.__next__())
dic = {'a':1,'b':2,'c':3}
iter_dic = dic.__iter__()
print(iter_dic.__next__())
迭代器对象的作用:提供了 不依赖索引取值的 手段
for循环原理(for循环本质就是一个while循环,只不过是一个一定可控的while循环)
dic = {'a': 1, 'b': 2, 'c': 3}
print(dic_iter.__next__()) # 打印结果为:a
print(dic_iter.__next__()) # 打印结果为:b
print(dic_iter.__next__()) # 打印结果为:c
print(dic_iter.__next__()) # 执行到此行报错
可迭代对象: 含有__iter__方法叫做可迭代对象 --> 除了数字类型都是可迭代对象 --> 可迭代对象使用__iter__变成迭代器
迭代器对象: 含有__iter__和__next__方法叫做迭代器对象 --> 只有文件是迭代器对象 --> 迭代器使用__iter__依然是迭代器
可迭代对象不一定是迭代器对象; 迭代器对象一定是可迭代对象
三元表达式
x = 10
y = 20
if x > y:
print(x)
else:
print(y)
三元表达式 --> 三目表达式
print(x) if x > y else print(y) # --> 仅作了解
条件成立走这里 if 条件 else 条件不成立走这里
列表推导式
要生成一个1到100的列表,可以用for循环
lt = []
for i in range(100):
lt.append(i)
上述方法繁琐,用列表推导式可以轻松实现
lt = [i for i in range(100)]
"for i in range(100)"是固定的结构,前边的i可以做其他运算,如下:
lt = [i**2 for i in range(10)]
要判断数据是什么类型,可用以下方法:
from typing import Iterable # 导出一个可迭代对象类型
print(isinstance(range(10),Iterable)) # 判断是否属于该数据类型
字典生成式
字典生成器:用于生成字典
要生成字典,我们可以用基本知识完成,过程如下:
dic = {}
for i in range(10):
dic[i] = i
print(dic)
也可以用类似与列表推导式的方法:
dic = {i:i**2 for i in range(10)}
print(dic)
重点:用zip方法将两个列表生成字典
lt1 = ['a', 'b', 'c']
lt2 = [1, 2, 3]
dic = {k: v ** 2 for k, v in zip(lt1, lt2)}
print(dic)
generator 生成器
generator 生成器: 本质就是迭代器,生成器就是一个自定义的迭代器
生成器:含有yield关键字的函数叫做生成器
def ge():
yield 3 # 一个yield相当于一个next; 暂停函数
yield 4
print(ge()) # ge()得到一个生成器 --> 生成器本质是迭代器
g = ge() # 得到一个生成器
print(g.__next__())
print(g.__next__())
yield的特性:
-
暂停函数
-
通过next取值
return的特性
-
终止函数
-
通过调用函数拿到值
生成器表达式
列表推导式:egg_list = ['鸡蛋%s' %i for i in range(10)],直接生成装满元素的列表。形象地称为一筐鸡蛋
生成器表达式:laomuji = ('鸡蛋%s' %i for i in range(10)), 这只是表达式,不取就不生成元素,取一次生出一个。形象的称为会下蛋的老母鸡
laomuji = ('鸡蛋%s' %i for i in range(10)) # 定义一个生成器
print(laomuji)
print(next(laomuji)) # 打印第一个值。next 等效于.__next__
print(laomuji.__next__()) # 打印第二个值
print(next(laomuji)) # 打印第三个值
一个一个取值就用print(next(laomuji))
一次取所有值就用print(list(laomuji))
生成器的优点:
1、延迟计算
一次返回一个结果。也就是说,它不会一次性生成所有的结果,这对于大数据量的处理会非常省时省空间。
2、代码简洁,提高可读性
练习题一
def demo():
for i in range(4):
yield i
g=demo()
g1=(i for i in g)
g2=(i for i in g1)
print(list(g1))
print(list(g2))
练习题二
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g=test()
for n in [1,10]:
g=(add(n,i) for i in g)
print(list(g))
递归函数
顾名思义传递并回归
递归: 函数a内部直接调用函数a本身
递归函数定义形式:
def a(): # 定义一个函数a
x = 1
print(x)
a() # 函数a内部调用自己
a() # 调用函数a
每一次递归,不会结束函数,并且每一次递归都会开辟内存空间,如果一直开辟内存就炸掉了,所以最多递归997次,python提供了修改递归次数的方法:
import sys
sys.setrecursionlimit(10000) # 把递归次数改为10000次
print(sys.getrecursionlimit())
真正的递归必须得要有 退出条件
count = 0
def a():
global count
count += 1
print(count)
if count == 5:
return
a()
a()
递归函数的要素:
-
函数内部调用函数自己
-
必须要有退出条件
-
递归必须要有规律
练习题:
1、小明20岁 ; 后面的同学大2岁,后面的后面的同学比后面的同学大2岁; 求第6位同学的年龄
def age(x):
if x == 0:
return 20
x -= 1
return age(x) + 2
res = age(3)
print(res)
2、小明买了一包瓜子,每天吃当天瓜子数量的一半,吃到第8天发现还剩5颗,用递归求他一共买了多少颗瓜子
def sum(x):
if x == 0:
return 5
x -= 1
return sum(x) * 2
res = sum(8)
print(res)