话不多说,上代码,看结果。
print('#########################9、闭包##################################')
# 在函数嵌套的前提下 内层函数引用了外层函数的变量(包括参数)
# 外层函数又把内层函数当做返回值进行返回
# 这个内层函数+所引用的外层变量, 称为 "闭包"
# 外层函数, 根据不同的参数, 来生成不同作用功能的函数
def fun3(x):
def fun4(y):
return x * y
return fun4
a = fun3(2)
b = a(5)
print(a)
print(b)
print(fun3(2)(5))
# 闭包中要修改引用的外层变量 需要使用nonlocal 变量声明
# 否则当做是闭包内, 新定义的变量
print('#############')
def fun5(x):
x = x
def fun6(y):
nonlocal x
x += 1
return x * y
return fun6
a = fun5(2)
b = a(5)
print(a)
print(b)
print(fun5(2)(5))
print('#########################10、装饰器##################################')
# 在函数名以及函数体不改变的前提下, 给一个函数附加一些额外代码
# 要装饰的函数无参数
# def fun7():
# print('fun7')
#
# fun7()
# 现在想在输出的fun7上面加print('##########')
def fun8(func):
def inner():
print('#######')
func()
return inner
@fun8 # fun7 = fun8(fun7)
def fun7():
print('fun7')
fun7()
# 要装饰的函数有参数
# 无论什么场景, 保证函数调用参数个数一致
# 为了通用, 可以使用不定长参数, 结合 拆包操作进行处理
def fun10(func):
def inner(*args, **kwargs):
print('@@@@@@')
func(*args, **kwargs)
return inner
@fun10 # fun9 = fun10(fun9)
def fun9(num, num2, num3):
print(num, num2, num3)
fun9(12, 13, num3=14)
# 对有返回值的函数进行装饰 无论什么场景, 保证函数返回值一致
def fun10(func):
def inner(*args, **kwargs):
print('^^^^^^^^^^^^^^^^^^^^^')
ret = func(*args, **kwargs)
return ret
return inner
@fun10 # fun9 = fun10(fun9)
def fun9(num, num2=13, num3=14):
print(num, num3)
return num, num3
fun9(12, num3=145)
# 带有参数的装饰器
# 通过@装饰器(参数)的方式, 调用这个函数, 并传递参数; 并把返回值, 再次当做装饰器进行使用
# 先计算 @ 后面的内容, 把这个内容当做是装饰器
# 在fun9输出上面打一行自己想要的符号
def fun11(char):
def fun10(func):
def inner(*args, **kwargs):
print(char * 10)
ret = func(*args, **kwargs)
return ret
return inner
return fun10
@fun11("~") # fun9 = fun10(fun9)
def fun9(num, num2=13, num3=14):
print(num, num3)
return num, num3
fun9(12, num3=145)
print('#########################11、生成器##################################')
# 是一个特殊的迭代器(迭代器的抽象层级更高)
# 生成器表达式
# 把列表推导式的[]修改成()
l = (i for i in (1, 2, 3) if i < 10)
print(next(l))
print(next(l))
print(l.__next__())
# print(l.__next__()) # StopIteration
print('1、#######')
# yield 语句
# yield可以去阻断当前的函数执行
# 再使用next()函数或__next__()都会让函数继续执行
# 当执行到下一个 yield语句的时候,又会被暂停
def fun12():
yield 1
print('a')
yield 2
print('b')
yield 3
print('c')
f = fun12()
print(f.__next__())
print(next(f))
print(next(f))
# print(next(f)) # StopIteration
# send() 方法
# send方法有一个参数,指定的是上一次被挂起的yield语句的返回值
# 相比于.__next__() 可以额外的给yield 语句 传值
# 注意第一次调用 t.send(None)
print('2、#######')
def fun12():
yield1 = yield 1
print(yield1)
print('a')
yield2 = yield 2
print(yield2)
print('b')
yield3 = yield 3
print(yield3)
print('c')
g = fun12()
print(g.send(None))
print('!!!')
print(g.send(123))
print('!!!')
print(next(g))
print('!!!')
# print(g.send(234)) # print(g.send(234))
# 关闭生成器
# g.close() 后续如果继续调用, 会抛出StopIteration异常提示
print('3、#######')
def fun13():
yield 1
print('a')
yield 2
print('b')
yield 3
print('c')
g = fun13()
print(next(g))
g.close()
# print(g.send(234)) # StopIteration
# 如果碰到return会直接终止, 抛出StopIteration异常提示
print('4、#######')
def fun14():
yield 1
print('a')
yield 2
print('b')
return 123
yield 3
print('c')
g = fun14()
print(next(g))
print(next(g))
# print(next(g)) # StopIteration: 123
# 生成器只会遍历一次!!!!!!!!!!!!!!!!!!!!
print('#########################13、函数作用域##################################')
# 1、基本概念
# (1)变量的作用域
# 变量的作用范围 可操作范围
# Python是静态作用域,也就是说在Python中,变量的作用域源于它在代码中的位置,在不同的位置, 可能有不同的命名空间
# (2)命名空间
# 是作用域的体现形式
# 不同的具体的操作范围
# (3)Python-LEGB
# L-Local 函数内的命名空间 作用范围: 当前整个函数体范围
# E-Enclosing function locals 外部嵌套函数的命名空间 作用范围: 闭包函数
# G-Global 全局命名空间 作用范围: 当前模块(文件)
# B-Builtin 内建模块命名空间 作用范围: 所有模块(文件)
# 注意 Python中没有块级作用域 块级作用域 代码块中, 比如 if while for 后的代码块
# LEGB规则 按照L -> E -> G -> B 的顺序进行查找
# 2、基于命名空间的常见变量类型
# (1)局部变量
# 在一个函数内部定义的变量;
# 作用域为函数内部
# 查看局部变量 locals()
# (2)全局变量
# 在函数外部, 文件最外层定义的变量
# 作用域为整个文件内部
# 查看全局变量 globals()
# 3、注意点
# 访问原则 从内到外
# 结构规范 全局变量 ->函数定义(使用、修改) ->后续代码
# 全局变量和局部变量重名
# 获取 就近原则
# 修改 global 全局变量声明
# l -> e unlocal
# 命名 全局变量 g_xxx
结果如下图
就先这样,遇到别的再补充。