一、匿名函数
1.匿名函数
匿名函数:没有函数名的函数,匿名函数可以看成是function类型的值,和10、‘abc’是同类东西
注意:匿名函数本质还是函数,函数除了声明语法以外其他的都适用于匿名函数
1)语法
lambda 参数列表:返回值
2)说明
lambda —— 关键字
参数列表 —— 参数名1, 参数名2, ... (相当于:函数名(变量名))
: —— 固定
返回值 —— 任何有结果的表达式;它是匿名函数的函数体,相当于普通函数的return语句
调用匿名函数:保存匿名函数值的变量(实参列表)
3)参数
普通函数中除了用参数名: 类型
的形式来定制参数类型以外,其他的语法匿名函数都支持
fn1 = lambda x, y: x + y
"""
def fn1(x, y):
x = 10, y = 30
return x+y
"""
fn2 = lambda x, y: print(x)
"""
def fn2(x, y):
x = 40, y = 20
print(x)
"""
print(fn1(10, 20))
fn2(40, 20)
print(fn2(40, 20))
100 # int类型的数据
'abc' # str类型的数据
[1, 2, 3] # list类型的数据
{'a': 10, 'b': 20} # dict类型的数据
lambda x: x # function类型的数据
a = 100 # int类型的数据
str1 = 'abc' # str类型的数据
list1 = [1, 2, 3] # list类型的数据
dict1 = {'a': 10, 'b': 20} # dict类型的数据
fn1 = lambda x: x # function类型的数据
print(a+10, str1.replace('a', 'A'), list1[0], fn1(90))
list2 = [100, 'abc', [1, 2, 3], lambda x: x*2]
print(list2)
print(list2[0]*10, list2[1][0], list2[-1](12))
sum1 = lambda x, y, z=3: x+y+z
sum3 = lambda *nums: sum(nums)
def sum2(x, y, z=0):
return x+y+z
print(sum2(10, 30), sum2(y=20, x=10))
print(sum1(1, 2), sum1(y=2, x=1))
print(sum3(1, 2, 3, 4, 5))
二、变量作用域
1.变量作用域
变量作用域:变量在程序中能够使用的范围
2.全局变量和局部变量
1)全局变量
没有声明在函数里面和类里面的变量就是全局变量;作用域是从声明开始到文件结束的任何位置
2)局部变量
声明在函数中的变量就是局部变量(函数的参数相当于声明在函数中的变量);作用域是从声明开始到函数结束的位置
3)函数调用过程(内存):压栈
当调用函数的时候,系统会自动在内存的栈区间为这个函数开辟一个独立的内存区域,用来保存在函数声明中的变量。当函数调用结束这个内存区域会自动释放。
print('================全局变量================')
a = 10 # 全局变量
# x是全局变量
for x in range(5):
if False:
c = 5 # 全局变量
b = 10 # b是全局变量
print('循环里面:a', a)
print('函数里面:x', x)
print('外面:b', b)
def func():
print('函数里面:a', a)
print('函数里面:x', x)
print('函数里面:b', b)
print('================局部变量================')
def func2(x1=20, y1=20):
z1 = 100
print('函数内部:x1, y1, z1', x1, y1, z1)
func2()
# print('函数外部:', x1) # NameError: name 'x1' is not defined
# print('函数外部:', z1) # NameError: name 'z1' is not defined
3.global和nonlocal(都在函数内部使用)
global和nonlocal函数中的关键字,和return一样只能在函数体中使用
1)global
global —— 在函数中声明一个全局变量
global 变量
变量 = 值
2)nonlocal
nonlocal —— 在局部的局部去修改局部变量的值 (在局部变量中必须存在该变量)
nonlocal 变量
变量 = 值
print('================global================')
a1 = 111 # 全局变量
b1 = 100 # 函数内有全局b1(b1=值),修改b1的值
def func3():
a1 = 222 # 这儿是在声明声明一个局部变量a
print('函数里面:a1', a1)
global b1 # 这儿的b1是全局变量
b1 = 333
print('函数里面:b1', b1)
func3()
print('函数外面:a1', a1)
print('函数外面:b1', b1)
print('================nonlocal================')
def func4():
a2 = 100 # SyntaxError: no binding for nonlocal 'a2' found
def func5():
# a2 = 500
nonlocal a2
a2 = 500
print('函数里面的函数里面:a2', a2)
func5()
print('函数里面:a2', a2)
func4()
# print(a2) # NameError: name 'a2' is not defined
def func(str):
# str = 'abc'
# sum = 0
print(str[1:])
func('hello world!')
三、函数递归
1.什么是函数递归
- 自己调用自己的函数(函数体中调用当前函数)
- 循环能做的事情,递归都可以做
注意:能用循环解决的问题就不要用递归
# RecursionError:
# maximum recursion depth exceeded
# while calling a Python object
# def func1():
# print('============')
# func1()
#
#
# func1()
2.怎么写递归函数
- 第一步: 找临界值(循环结束的条件)—— 在这儿需要结束函数
- 第二步:找关系 —— 找f(n)和f(n-1)的关系(找当次循环和上次循环的关系)
- 第三步:假设函数的功能已经实现,根据关系用f(n-1)去实现f(n)的功能
# 用递归函数实现:1+2+3+...+n
def sum1(n):
# 第一步:找临界值
if n == 1:
return 1
# 第二步:sum1(n)和sum(n-1)
# sum1(n) == 1+2+3+...+n-1+n
# sum1(n-1) == 1+2+3+...+n-1
return sum1(n-1) + n
print(sum1(100))
# 用递归函数求斐波那契数列中第n个数:
# 1, 1, 2, 3, 5, 8, 13, 21
def fibonacci(n):
if n == 1 or n == 2:
return 1
# 找关系:sequence(n)和sequence(n-1)
# sequence(n) = sequence(n-1) + sequence(n-2)
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(8))
# 练习:用递归实现以下功能
"""
n = 5
*****
****
***
**
*
n = 4
****
***
**
*
"""
def print_star(n):
if n == 1:
print('*')
return
# 找关系:打印n个*,再实现f(n-1)的功能
else:
print('*'*n)
return print_star(n-1)
print_star(5)
# 练习:用递归实现以下功能
"""
n = 3
*
**
***
n = 4
*
**
***
*****
"""
print('=================================')
def print_star(n):
if n == 1:
print('*')
return
# 找关系:打印n个*,再实现f(n-1)的功能
else:
print_star(n-1)
print('*' * n)
print_star(3)
四、迭代器
1.迭代器(iter)
迭代器作为容器可以保存多个数据;数据的来源:
1)将其他序列转换成迭代器
2)生成器
# 1)将其他序列转换成迭代器
iter1 = iter('abc')
print(iter1, type(iter1))
# <str_iterator object at 0x000000000209C408>
# <class 'str_iterator'>
iter2 = iter([12, 30, 90])
print(type(iter2)) # <class 'list_iterator'>
2.获取元素
不管用哪种方式获取了元素的值,那么这个元素在迭代器中就不存在了
1)获取单个元素
①next(迭代器)
②迭代器.__next__()
上述①②都是获取迭代器中的第一个元素
2)遍历
for 变量 in 迭代器:
iter3 = iter('hello')
print(iter3.__next__())
print(next(iter3))
print(iter3.__next__())
print(next(iter3))
# for x in range(100):
# print(x)
print(next(iter3))
# print(next(iter3.__next__())) # StopIteration
# 如果迭代器为空,用next获取元素的时候会报错
iter4 = iter('world')
for x in iter4:
print(x)
# print(next(iter4)) # StopIteration
print('=========')
iter4 = iter('world')
print(iter4.__next__())
for x in iter4:
print('循环', x)
五、生成器
1.什么是生成器
1)生成器就是迭代器中的一种
2)调用一个带有yield关键字的函数就可以得到一个生成器
如果一个函数中有yield关键字:
a. 调用函数不会执行函数体
b.函数调用表达式的值不是函数的返回值,而是一个生成器对象
# 怎么去创建一个生成器
def func1():
print('=============')
if False:
yield
return 100
gen1 = func1() # 这个的gen1就是一个生成器对象
print('外部:', gen1)
2.生成器产生数据的原理
1)一个生成器能够产生多少个数据,就看执行完生成器对应的函数的函数体会遇到几次yield,yield后面的值就是生成器能够产生的数据
2)每次获取生成器的时候都会执行函数体,直到遇到yield,并且将yield后面的值作为获取元素的结果;并且保留结束的位置,下次获取下一个值的时候,从上次结束的位置接着执行函数体直到遇到yield...
如果从开始执行到函数结束都没有遇到yield,就会报StopIteration错误
print('=====================2=====================')
def func2():
print('++++')
yield
print('------')
yield 100 # yield后边可以跟数据;同一个函数可以有多个yield
gen2 = func2()
print(gen2)
print('函数外部', next(gen2))
print(next(gen2))
# print(next(gen2)) # StopIteration
def func3():
print('第一段代码')
yield
print('第二段代码')
yield
print('第三段代码')
yield
gen3 = func3()
next(gen3)
time.sleep(1)
next(gen3)
time.sleep(1)
next(gen3)
# 练习:
def func4():
for x in range(0, 100, 3):
yield x
print(next(func4()))
print(next(func4()))
print(next(func4()))
gen4 = func4()
print(next(gen4)) # 0
print(next(gen4)) # 3
print(next(gen4)) # 6