01迭代器
-
1.什么是迭代器(iter)
- 迭代器是容器型数据类型(序列),迭代器无法直接获取左右元素,也不能统计元素个数
- 获取迭代器中的元素的时候,会导致这个元素从迭代器中消失。元素取一个就少一个。
-
2.创建迭代器
- 创建迭代器只有两种方式:1)将其他序列转换成迭代器 2)创建生成器
iter1 = iter('abc')
print(iter1) # <str_iterator object at 0x000002295E1CE6C8>
iter2 = iter([10,20,30])
print(iter2) # <list_iterator object at 0x000001982A534408>
iter3 = iter([{'a':10},{'b':20}])
print(iter3) # <list_iterator object at 0x000001982A12F4C8>
-
3.获取迭代器中的元素
- 1)获取单个元素:next(迭代器)
print(next(iter1)) # a print(next(iter1)) # b print(next(iter1)) # c # print(next(iter1)) # 报错 StopIteration print(next(iter3)) # {'a': 10} print(next(iter3)) # {'b': 20}
-
2)遍历
for x in iter2: print(f'x:{x}') # x:10 # x:20 # x:30 # iter4 = iter([10,20,30]) # list1 =[] # for x in range(3): # list1.append(next(iter4)) # print(list1)
02 生成器
- 1.生成器
- 生成器从获取数据和保存特点来看,就是迭代器
- 生成器保存数据的本质不是保存数据本身,而是保存产生数据的算法
- 2.创建生成器
- 调用带有yield关键字的函数就可以得到一个生成器
- 调用带有yield关键字的函数的不会执行函数体, 也不会获取函数返回值,
- 只是单纯的创建一个生成器(函数中yield在哪没有关系).
def func1():
print('======')
return 100
result = func1()
print(result)
# ======
# 100
def func1():
yield
print('======')
return 100
result = func1()
print(result)
# <generator object func1 at 0x000001E34FFBA848> result就是一个生成器
-
3.确定生成器的元素 - 生成器可以创造的数据
- 一个生成器能产生多少个数据就看这个生成器对应的函数, 执行完函数会遇到几次yield
- 每次遇到yield的时候yield后面的数据就是产生的数据
-
生成器产生数据的原理
- 当通过生成器对象获取元素(不管以什么样的方式获取)的时候, 系统会自动执行生成器对应的函数, 执行函数的时候不会将整个函数执行完,
- 而是每次在执行yield的时候就会停下来, 并且将yield后面的数据作为结果返回,
下次再获取元素的时候是从上次结束的位置开始执行
def fun2():
print('=====')
yield 100
yield 200
yield 300
# if 2>10:
# yield 400 # 无效
# return
# yield 500 # 无效
result = fun2() # 这里只是调用,没有执行函数体,不会打印fun2()d的'===='
print(next(result)) # 100
print(next(result)) # 200
print(next(result)) # 300
# print(next(result)) # StopIteration
- 4.生成器产生数据的原理
- 当通过生成器对象获取元素(不管以什么方式获取)的时候,系统会自动执行生成器对应的函数,
执行函数的时候不会直接将整个函数执行完 - 而且再获取元素的时候,是从上次结束的位置开始执行
- 当通过生成器对象获取元素(不管以什么方式获取)的时候,系统会自动执行生成器对应的函数,
def func3():
print('11111111')
yield 100
print('22222222')
yield 200
print('33333333')
yield 300
print('44444444')
result = func3() # result是一个生成器,里面有关键字yield
print(next(result)) # 开始执行到第一个yield就停下来,下一次从这里开始执行到下一个yield
# 11111111
# 100
print('!!!!!')
print(next(result))
# 22222222
# 200
print('------')
for x in result:
print(f'x:{x}')
# 33333333 # 从上次结束的地方开始执行
# x:300
# 44444444 # 在尝试去取下一个yield的时候,打印了444444
def func4():
yield print('abc')
result = func4()
print(next(result))
# abc
# None
# 打印none是因为没有返回值
# 打印'abc'是因为执行函数的时候打印
def func5():
yield 10
yield 20
yield 30
yield 40
yield 50
print(next(func5())) # 10 创造一个新的生成器,没有保存
print(next(func5())) # 10 创造一个新的生成器
result = func5() # 值创建一个生成器
print(next(result)) # 10 再用
print(next(result)) # 20
# 练习:写一个创建学生学号的生成器,要求产生的学号前缀是python,后面是指定范围的值。
# 26 ~ 56 -> python0026 ~ python0056
# def func6(str1,num1,num2):
# for x in range(num1,num2):
# pass
#
# result = func6('python',26,56)
# print(result)
def study_num(suject,num1,num2):
for x in range(num1,num2+1):
yield f'{suject}{str(x).zfill(4)}'
creater = study_num('python',126,156)
print(next(creater))
java = study_num('java',1,20)
print(next(java))
03装饰器
- 1.什么是装饰器
- 装饰器 = 实参高阶函数 + 返回值高阶函数 +糖语法 (装饰器的本质是函数)
- 作用:给已经定义好的函数添加功能
import time
# 给函数添加功能解决方法一:在需要添加功能的所有函数中添加新功能对应的代码
def func1():
start = time.time()
print('hello world!')
end = time.time()
print(f'函数执行时间:{end-start}')
func1()
def func2(a,b):
start = time.time()
print(a+b)
end = time.time()
print(f'函数执行时间:{end-start}')
func2(23,45)
- 2.无参装饰器的实现方法
-
装饰器的工作原理:将需要添加功能的函数传给装饰器,装饰器创建一个保留原函数功能的一个新函数,将添加完功能的新函数返回,左后用新的函数替换原来的函数。
-
装饰器的套路:
def 函数1(参数1:function):
def 函数2(*args,**kwargs):
添加新功能
result = 参数1(*args,**kwargs)
return result # 这里不能改
return 函数2 -
函数1 - 装饰器功能对应的名字
-
参数1 - 类型是function , 指向需要添加功能的原函数,fn
-
函数名2 - 指向添加完功能的新函数,习惯命名成new_fn
-
def 装饰器名(fn):
def new_fn(*args,**kwargs):
新功能
result = fn(*args,**kwargs)
return result
return new_fn
-
#装饰器:+end
def add_end_message(fn):
def new_fn(*args,**kwargs):
result = fn(*args,**kwargs)
print('end')
return result
return new_fn
#装饰器:+100
def add_100(fn):
def new_fn(*args,**kwargs):
result = fn(*args,**kwargs)
if type(result) in (int,float):
return result+100
return new_fn
@add_end_message
@add_100
def func3(num:int):
sum1 = 1
for x in range(1,num+1):
sum1 *=x
return sum1
print('=======')
# x=func3(3) # 调用
print(func3(3)) # 调用之后再打印
# =======
# end
# 6
@add_end_message
@add_100
def func4():
return 'hello world!'
print('========')
print(func4())
# ========
# end
# hello world!
# =======
# end
# 106
# ========
# end
# None
# 装饰器:变字符串
def change_str(fn):
def new_fn(*args,**kwargs):
result ="'"+ str(fn(*args,**kwargs)) +"'"
return result
return new_fn
@change_str
def func5():
return 100
print('++++++')
print(func5())
03递归函数
-
1.递归函数
- 在定义函数的时候调用函数本身
- 理论上,循环能做的事情,递归都能做(能循环实现的不要用递归)
- 注意:使用递归解决循环问题的时候,内存和CPU的消耗会随着循环次数的增加而不断增加
def fn(): print('hello') fn() # fn() # RecursionError: maximum recursion depth exceeded while calling a Python object
-
2.使用递归的套路
- 第一步:找临界值(循环结束的条件),在临界值的位置结束函数 (例如 n==1 时,return)
- 第二步:找关系,找上一次循环结束的结果和当此循环结束的结果的关系
- 第三步:假设函数功能已经实现,通过关系用f(n-1)实现f(n)的功能
# 计算1+2+3+...100
def sum1(num):
if num == 1:
return 1
else:
return num + sum1(num - 1)
print(sum1(100))
# 1 1 2 3 5 8
def num(n):
if n == 1 or n == 2:
return 1
return num(n-1)+num(n-2)
print(num(4))
# 2.打印下列图形
"""
n=3
*
**
***
"""
def star(n):
if n == 1:
print('*')
return
star(n-1)
return print('*'*n)
star(3)
作业
-
为函数写一个装饰器,在函数执行之后输出 after
def add_after_message(fn): def new_fn(*args,**kwargs): result = fn(*args,**kwargs) print('after') return result return new_fn @add_after_message def func1(num:int): sum1 = 1 for x in range(1,num+1): sum1 *=x return sum1 print(func1(3))
-
为函数写一个装饰器,把函数的返回值 乘2再返回值
def plus_two(fn): def new_fn(*args,**kwargs): result = fn(*args,**kwargs) if type(result) in (int,float): return result*2 return new_fn @plus_two def func1(num:int): sum1 = 1 for x in range(1,num+1): sum1 *=x return sum1 print('=======') print(func1(3))
-
写一个装饰器@tag要求满足如下功能:
@tag
def render(text):
# 执行其他操作
return text
@tag
def render2():
return 'abc'
print(render('Hello')) # 打印出: <p>Hello</p>
print(render2()) # 打印出: <p>abc</p>
def tag(fn):
def new_fn(*args,**kwargs):
result = "<p>"+str(fn(*args,**kwargs))+"/<p>"
return result
return new_fn
@tag
def render(text):
# 执行其他操作
return text
@tag
def render2():
return 'abc'
print(render('Hello')) # 打印出: <p>Hello</p>
print(render2()) # 打印出: <p>abc</p>
- 写一个创建一副扑克牌的生成器。
def card(huapy,nums):
for x in hua:
for y in nums:
yield f'{x}{y}'
yield '小王'
yield '大王'
str1 = ['方块','红桃','梅花','黑桃']
str2 = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
result = card(str1,str2)
print(next(result))
- 使用递归函数画出以下图形:
n = 5
*****
****
***
**
*
n = 4
****
***
**
*
def star(n):
if n == 1:
print('*')
return
print('*' * n)
star(n-1)
star(4)