一、嵌套函数
1.1概念
嵌套函数是定义在另一个函数作用域内部的函数。外部函数可以访问其内部声明的嵌套函数,而嵌套函数则可以访问其外部函数的作用域(包括参数和局部变量)。
1.2实例
一般情况下,我们是这样书写嵌套函数的,通过funA来访问funB
def funA():
x=123;
def funB():
print(x)
funB()
funA()
这里我们也可以把funB()修改为return funB
这样当funA被调用时,他不会立即执行funB,而是返回funB函数对象的引用。这意味着你可以将funB作为一个值传递给其他函数或者稍后调用它
一般情况下,当我们执行完funny=funA()之后,funA内的局部变量就会被释放,但我们通过funny()仍然可以访问x的值,这就说明外层变量被保存下来了,没有释放,这就是我们接下来要说的闭包。
def funA():
x=123;
def funB():
print(x)
return funB
#调用funB
funA()()
#funA得到的事funB函数的一个引用
#当我们不想通过funA来调用funB时,就可以把funA赋值给一个变量
funny=funA()
funny()
这里要注意,在第五行中我们要写return funB,千万不要写成return funB()
return funB:表示返回funB函数对象本身,而不是调用,因此当外层的 funA函数执行到return funB时,返回的是funB函数的一个引用
return funB():表示调用funB函数,并返回它的执行结果,而在funB函数中没有return函数,所以默认返回None,因此当funA执行return funB()时,它实际上返回的是None,然后你把funA的返回值赋值给变量funny,然后通过funny()想调用funB,会造成TypeError,因为NoneType对象是不可以调用的
二、函数闭包(closure)
2.1定义
一般情况下,在外层函数执行结束之后,局部变量会被回收,如果有内部函数仍然需要访问这些变量,Python解释器会保留这些变量的引用,直到内部函数不再需要它们为止。
2.2实例
调用square来实现平方,调用cube来实现立方
def power(exp):
def exp_of(base):
print(base ** exp)
return exp_of
square=power(2)
cube=power(3)
square(3)
cube(2)
三、nonlocal
- 用于嵌套函数中申明对外层函数中局部变量的引用或修改
- 允许嵌套函数修改外层函数中的变量
3.1实例1
def out():
count=0
def inner():
nonlocal count
count +=1
print(f"count={count}")
return inner
funny=out()
funny()
funny()
3.2实例2
def outer():
x=0
y=0
def inner(x1,y1):
nonlocal x,y
x+=x1
y+=y1
print(f"现在 x=({x},y={y})")
return inner
move=outer()
move(1,2)
move(-2,2)
四、global
- 用于在函数内部生命一个变量是全部变量,而不是局部变量
- 允许函数内部修改全局变量的值
4.1实例1
count = 0
def out():
def inner():
global count
count+=1
print(f"count={count}")
return inner
funny=out()
funny()
funny()
五、装饰器(decorator)
5.1定义
装饰器的工作原理:自动将装饰器语法后紧挨着的函数作为参数传递给装饰器函数(这个过程是隐式的),并返回一个新的函数
应用装饰器:使用@将装饰器应用于目标函数或方法
调用目标函数:当前目标函数被调用时,实际上执行的是装饰器返回的新函数
5.2实例
5.2.1装饰器
import time
def time_decorator(func):
def call_func():
print("start...")
start=time.time()
func()
stop=time.time()
print("stop...")
print(f"spend {(stop-start):.2f}s")
return call_func
#使用装饰器
@time_decorator
def myfunc():
time.sleep(2)
print("hello world")
myfunc()
还原就是这样
import time
def time_decorator(func):
def call_func():
print("start...")
start=time.time()
func()
stop=time.time()
print("stop...")
print(f"spend {(stop-start):.2f}s")
return call_func
def myfunc():
time.sleep(2)
print("hello world")
myfunc=time_decorator(myfunc)
myfunc()
5.2.2 多个装饰器同时用在同一个函数上
调用顺序为cube->square->add
def add(func):
def inner():
x=func()
return x+1
return inner
def square(func):
def inner():
x=func()
return x*x
return inner
def cube(func):
def inner():
x=func()
return x*x*x
return inner
@add
@square
@cube
def test():
return 2
print(test())
还原就是这样
def add(func):
def inner():
x=func()
return x+1
return inner
def square(func):
def inner():
x=func()
return x*x
return inner
def cube(func):
def inner():
x=func()
return x*x*x
return inner
def test():
return 2
#这里的func1是一个新的函数
func1=cube(test)
#再将func1传入到square中
func2=square(func1)
func3=add(func2)
func1()
func2()
x=func3()
print(x)
5.2.3给装饰器传递参数
import time
def logger(msg):
def time_func(func):
def call_func():
start=time.time()
func()
stop=time.time()
print(f"[{msg}]speed{(stop-start):.2f}s")
return call_func
return time_func
@logger(msg='A')
def funA():
time.sleep(1)
print("调用funA...")
@logger(msg='B')
def funB():
time.sleep(1)
print("调用funB...")
funA()
funB()
还原就是这样
import time
def logger(msg):
def time_func(func):
def call_func():
start=time.time()
func()
stop=time.time()
print(f"[{msg}]speed{(stop-start):.2f}s")
return call_func
return time_func
def funA():
time.sleep(1)
print("调用funA...")
def funB():
time.sleep(1)
print("调用funB...")
funA=logger('A')(funA)
funB=logger('B')(funB)
funA()
funB()
六、列表推导式
6.1定义
6.1.1语法
- expression:这是你想要生成列表中每个元素的表达式。
- item:这是当前正在处理的迭代项。
- iterable:这是你想要从中生成列表的可迭代对象,如列表、元组、字符串或任何其他可迭代对象。
- condition(可选):这是一个可选的条件表达式,用于确定哪些项应该被包含在最终列表中。只有满足条件的项才会被包括。
6.2实例
6.2.1 生成一个0-9的平方的列表
square =[x*x for x in range(10)]
print(square)
6.2.2 将字符串转换为大写/小写
strings=["hello","world"]
upper_strings=[s.upper() for s in strings]
print(upper_strings)
strings1=["PYTHON","BETTER"]
upper_strings1=[s.lower() for s in strings1]
print(upper_strings1)
6.2.3嵌套列表
matrix=[[1,2,3],[4,5,6],[7,8,9]]
change=[[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(change)
展开是这样的
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [] # 初始化一个空列表,用于存储转置后的矩阵
# 外层循环遍历列索引
for i in range(len(matrix[0])):
# 为每一列创建一个新列表
column = []
# 内层循环遍历所有行
for row in matrix:
# 将当前行的第i个元素添加到column列表中
column.append(row[i])
# 将这一列添加到转置后的矩阵中
transposed.append(column)
# 输出转置后的矩阵
print(transposed)
七、生成器(generator)
7.1定义
7.2使用
- 生成器函数使用yield关键字而不是return来返回值
- 每次调用生成器的__next__()方法(或者通过next()函数)时,它会执行到下一个yield语句,并返回相应的值。生成器函数会在遇到yield时暂停执行,并在下次调用时从暂停的地方继续执行。
7.3实例
7.3.1简单使用生成器
def counter():
i=0
while i<=5:
yield i#每次调用到该语句就生成一个新数据
i+=1
for i in counter():
print(i,end=' ')
7.3.2使用next()函数
def counter():
i=0
while i<=5:
yield i#每次调用到该语句就生成一个新数据
i+=1
c=counter()
print(next(c))
print(next(c))
当访问越界之后就会报错
生成器每次只会生成一个对象,所以也不能使用下标访问
def counter():
i=0
while i<=5:
yield i#每次调用到该语句就生成一个新数据
i+=1
c=counter()
print(c[2])
7.3.2使用生成器打印斐波那契数列
def fib():
back1,back2=0,1
while True:
yield back1
back1,back2 = back2,back1+back2
f=fib()
for i in f:
if(i>1000):
break
print(i)
但这里要注意一个问题
下面的代码这样写是有问题的,会陷入无限循环,因为外部for循环迭代的是生成器f,它会不断产生新的斐波那契数,而内部的while循环则设置了要小于10000,然而外部循环没有终止条件,它将永远持续下去,即使内部的while循环在某次迭代后不再执行,外部循环仍然会要求生成器产生下一个数字
def fib():
back1,back2=0,1
while True:
yield back1
back1,back2 = back2,back1+back2
f=fib()
for i in f:
while(i<1000):
print(i,end=' ')
7.4生成器表达式
生成器表达式语法与列表推导式非常相似,但不同之处在于生成器表达式使用()而不是[]
t=(i**2 for i in range(10))
for i in t:
print(i,end=' ')