闭包
在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。
实例
def func():
name="张书源"
def inner():
print("My name is :",name)
return inner
f=func()
f()
如何判断是否是闭包函数
函数名.__closure__
在函数是闭包函数时,返回一个cell元素;不是闭包时,返回None。
def func():
name = '张书源'
def inner():
print("My name if :",name)
print(inner.__closure__) # (<cell at 0x0000027C14EB85E8: str object at 0x0000027C14F54960>,)
return inner
f = func()
f()
name = '张书源'
def func():
def inner():
print("My name is :",name)
print(inner.__closure__) # None
return inner
f = func()
f()
装饰器
装饰器是给现有的模块增添新的小功能,可以对原函数进行功能扩展,而且还不需要修改原函数的内容,也不需要修改原函数的调用。
装饰器的使用符合了面向对象编程的开放封闭原则。
简单的装饰器
def Time_sleep():
print("Time sleep 函数启动")
time.sleep(2)
def count_time(func): #函数运行时间计时器
def wrapper():
ti = time.time()
func()
print("执行时间为:", time.time() - ti)
return wrapper
if __name__ == '__main__':
Time_sleep = count_time(Time_sleep)
Time_sleep()
这里的count_time是一个装饰器,装饰器函数里面定义一个wrapper函数,把func这个函数当作参数传入,函数实现的功能是把func包裹起来,并且返回wrapper函数。wrapper函数体就是要实现装饰器的内容。
装饰器的语法糖@
import time
import time
def count_time(func):
def wrapper():
t1 = time.time()
func()
print("执行时间为:", time.time() - t1)
return wrapper
@count_time
def Time_sleep():
print("Time sleep 函数启动")
time.sleep(2)
if __name__ == '__main__':
Time_sleep() # 用语法糖之后,就可以直接调用该函数了
装饰器传参
当被装饰的函数是带参数时,例如
def blog(name):
print('进入blog函数')
name()
print('我的博客是 https://blog.csdn.net/qq_52902529')
装饰器函数修改成为可以接受任意参数的装饰器,参数为*args和**kwargs,表示可以接受任意参数
def count_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
func(*args, **kwargs)
print("执行时间为:", time.time() - t1)
return wrapper
带参数的装饰器
基于原来的count_time函数外部再包一层用于接收参数的count_time_args,接收回来的参数就可以直接在内部的函数里面调用了
import time
def count_time_args(msg=None):
def count_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
func(*args, **kwargs)
print(f"[{msg}]执行时间为:", time.time() - t1)
return wrapper
return count_time
@count_time_args(msg="张书源")
def fun_one():
time.sleep(1)
@count_time_args(msg="张硕")
def fun_two():
time.sleep(1)
@count_time_args(msg="汤康丽")
def fun_three():
time.sleep(1)
if __name__ == '__main__':
fun_one()
fun_two()
fun_three()
lambda表达式
- lambda只是一个表达式,函数体比def简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
实例:
sum=lambda a,b:a+b
print("1 + 2 = ", sum(1 , 2))
生成器(gengerator)
生成器是python中的一个对象(按照某种规律,来生成元素的对象),生成器不是列表,保存了产生元素的算法,同时会记录游标的位置(现在拿到第几个元素了),为了下次继续拿数据,而不是从头开始拿数据。可以通过一直调用next()方法获取值,这个对象不保存数据,每次调用会返回一个值,即做到了列表的好处,又不占用空间。
通过类似于列表生成式来创建(将列表换为元组)
list2=(x for x in range(1,11))
print(list2) #<generator object <genexpr> at 0x0000020B66A4BF20>
print(type(list2)) #<class 'generator'>
通过函数创建生成器(yield)
def counter():
i=0
while i<=5:
yield i #yield:是没有返回值的,如果赋值的话会打印None
i+=1
gener=counter()
print(gener) #<generator object counter at 0x00000295F518BF20>
for x in gener:
print(x) # 0 1 2 3 4 5
遍历生成器中的元素
next(生成器对象)
每调用一次next(),就会拿掉一个值(表达式中的第一个值),当已经遍历到生成器的结尾,会抛一个异常StopIteration。
def counter():
i=0
while i<=5:
yield i
i+=1
gener=counter()
print(next(gener))# 0
print(next(gener))# 1
print(next(gener))# 2
print(next(gener))# 3
print(next(gener))# 4
print(next(gener))# 5
print(next(gener))# 报错
for循环遍历
for x in gener:
print(x) #不会抛出异常
生成器对象.next()
object内置的__next__,当已经遍历到生成器的结尾,会抛一个异常StopIteration
print(gener.__next__())
list(g)方法
print(list(gener))
生成器内置方法
close() --关闭生成器
send()
和next一样可以用来生成数据,可以往生成器内部传递数据(可以和生成器内部进行交互)
def generator_function():
value1 = yield 1
value1 = yield 0
print("value1的值是 : ",value1)
value2 = yield 1
print("value2的值是 : ",value2)
value3 = yield 2
print("value3的值是 : ",value3)
g=generator_function()
print(g.__next__())
print(g.send(1))
g.send(1)
print(g.send(2))
在上面的代码中,我们先调用 next() 方法,使函数开始执行,代码执行到 yield 1 的时候暂停,返回了 1;接着,我们执行了 send() 方法,它会恢复生成器的运行,并将发送的值赋给上次中断时 yield 表达式的执行结果,也就是 value1,这时我们又执行了send()方法控制台打印出 value1 的值,并继续执行,直到遇到 yield 后暂停,此时返回 2;类似地,再次执行 send() 方法,将值赋给value2。
简单地说, send() 方法就是 next() 的功能,加上传值给 yield 。