内部函数
# 内部函数
'''
特点:
1. 可以访问外部函数的变量
2. 内部函数可以修改外部函数的可变类型的变量比如:list1
3. 内部函数修改全局的不可变变量时,需要在内部函数声明global 变量名
内部函数修改外部函数的不可变的变量时,需要在内部函数中声明: nonlocal 变量名
4. locals() 查看本地变量有哪些,以字典的形式输出
globals() 查看全局变量有哪些,以字典的形式输出(注意里面会有一些系统的键值对)
'''
def func():
# 声明变量
n = 100 # 局部变量
list1 = [3, 6, 9, 4] # 局部变量
# 声明内部函数
def inner_func():
nonlocal n
# 对list1里面的元素进行加5操作
for index, i in enumerate(list1):
# 0 3
list1[index] = i + n
list1.sort()
# 修改n变量
n += 101
# 调用一下内部的函数
inner_func()
print('打印老大n:',n) #打印老大n: 201
print('打印老二list1:',list1) #打印老二list1: [103, 104, 106, 109]
# 调用func
func()
locals() globals()
a = 100 # 全局变量
print(globals())
#{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000012F0E362F28>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/Python Script/demo-01.py', '__cached__': None, 'a': 100}
# 定义函数
def func():
# 声明变量
b = 99
# 声明函数
def inner_func():
global a
nonlocal b
c = 88
# 尝试修改
c += 12
b += 1
a += 10
# 尝试打印
print(a, b, c) #110 100 100
# 调用内部函数
inner_func()
# 使用locals()内置函数进行查看。可以看到在当前函数中声明的内容有哪些
# locals()是一个字典。key:value
print(locals()) #{'inner_func': <function func.<locals>.inner_func at 0x0000012F0E838EA0>, 'b': 100}
# 调用函数
func()
闭包
# 闭包
# 在函数中提出的概念,
'''
条件:
1. 外部函数中定义了内部函数
2. 外部函数是有返回值
3. 返回的值是:内部函数名
4. 内部函数引用了外部函数的变量
格式:
def 外部函数():
...
def 内部函数():
....
return 内部函数
'''
def func():
a = 100
def inner_func():
b = 99
print(a, b)
print(locals()) #{'inner_func': <function func.<locals>.inner_func at 0x0000013C88BA8EA0>, 'a': 100}
return inner_func
# print(a)
# inner_func()
x = func()
print(x) # <function func.<locals>.inner_func at 0x00000000021500D0>
# x就是内部函数,x()就表示调用函数
x() #100 99
# 闭包
def func(a, b):
c = 10
def inner_func():
s = a + b + c
print('相加之后的结果是:', s)
return inner_func
# 调用func
ifunc = func(6, 9) # ifunc就是inner_func ifunc = inner_func
# 调用返出来的内部函数
ifunc()
闭包的应用
def func(a, b):
c = 10
def inner_func():
s = a + b + c
print('相加之后的结果是:', s)
return inner_func
# 调用func
ifunc = func(6, 9) # ifunc就是inner_func ifunc = inner_func #<function func.<locals>.inner_func at 0x0000029AB5568EA0>
ifunc1 = func(2, 8) #<function func.<locals>.inner_func at 0x0000029AB5568F28>
ifunc2 = func(1, 9) #<function func.<localsa>.inner_func at 0x0000029AB556F048>
print(ifunc) #相加之后的结果是: 20
print(ifunc1) #相加之后的结果是: 25
print(ifunc2) #相加之后的结果是: 20
ifunc1()
ifunc()
ifunc2()
# 计数器
def generate_count():
container = [0]
def add_one():
container[0] = container[0] + 1 # [2]
print('当前是第{}次访问'.format(container[0]))
return add_one
# 内部函数就是一个计数器
counter = generate_count() # counter = add_one
counter() # 第一次的访问 #1
counter() # .... #2
counter() #3
'''
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,
并且把里面的函数返回,我们把这种情况叫闭包
内部函数对外部函数作用域里变量的引用
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。
访问外部函数的可变类型局部变量可不加nonlocal
访问外部函数的不可变类型局部变量要加 nonlocal
闭包有什么缺点呢?
闭包的缺点1,作用域没有那么直观
闭包的缺点2,因为变量不会被垃圾回收所以有一定的内存占用问题。
闭包作用:1.可以使用同级的作用域
闭包作用:2.读取其他元素的内部变量
闭包作用:3.延长作用域
闭包总结
1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成.
2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存.
3.闭包的好处,使代码变得简洁,便于阅读代码。
4.闭包是理解装饰器的基础
'''
def func():
a = 100
def inner_func1():
b = 90
s = a + b
print(s) #<function func.<locals>.inner_func2 at 0x000002A1E7C78F28>
def inner_func2(): # define
inner_func1() # 调用inner_func1
print('-----------> inner_func2',a) #190
return 'hello'
return inner_func2 # 0x0000000001DE0158
# 调用func
f = func()
print(f) # <function func.<locals>.inner_func2 at 0x000001DDF1588F28>
ff = f() # inner_fun2()
print(ff) #
#190
#-----------> inner_func2 100
#hello
装饰器
# 装饰器
'''
加入购物车,付款,修改收货地址,。。。
判断用户的登录状态
'''
#返回函数
def func(number):
a = 100
def inner_func():
nonlocal a
nonlocal number
number += 1
for i in range(number):
a += 1
print('修改后的a:', a) #修改后的a: 106
return inner_func
# 调用func
f = func(5)
f()
# 函数作为参数
a = 50
f1 = func(a) # a是一个实参
print(f1) #<function func.<locals>.inner_func at 0x000001DFD1038F28>
# 地址引用
a = 10 # 声明整型变量
b = a
def test(): # 声明函数
print('------test-------')
# t = test
# test() #------test-------
# t() ------test-------
# def func(f): # f=test
# print(f) # <function test at 0x0000000001D01E18>
# f() # -------test---------
# print('------------>func')
#
#
# # 调用
# func(test)
'''
特点:
1. 函数A是作为参数出现的(函数B就接收函数A作为参数)
2. 要有闭包的特点
'''
# 定义一个装饰器
def decorate(func):
a = 100
print('wrapper外层打印测试')
def wrapper():
func()
print('--------->刷漆')
print('--------->铺地板', a)
print('--------->装门')
print('wrapper加载完成......')
return wrapper
# 使用装饰器
@decorate
def house():
print('我是毛坯房....')
'''
默认执行的:
1. house被装饰函数,
2. 将被装饰函数作为参数传给装饰器decorate
3. 执行decorate函数
4. 将返回值又赋值给house
'''
print(house) ##<function decorate.<locals>.wrapper at 0x00000207B1B10048>
house()
#wrapper外层打印测试
#wrapper加载完成......
#<function decorate.<locals>.wrapper at 0x00000207B1B10048>
#我是毛坯房....
#--------->刷漆
#--------->铺地板 100
#--------->装门
# def house1():
# house()
# print('刷漆')
# print('铺地板')
# 调用函数house
# house()
装饰器参数(万能装饰器)
# 登录校验
import time
def decorate(func):
def wrapper(*args, **kwargs): # () {'clazz':'1904'}
print('正在校验中....')
time.sleep(2)
print('校验完毕.....')
# 调用原函数 args --->()
func(*args, **kwargs) # f1 f2 f3...
return wrapper
@decorate
def f1(n):
print('-------f1-------', n)
f1(5) # 此时的f1是wrapper,
@decorate
def f2(name, age):
print('-------f2-------', name, age)
f2('lily', 20)
#
#
@decorate
def f3(students, clazz='1905'):
print('{}班级的学生如下:'.format(clazz))
for stu in students:
print(stu)
students = ['lily', 'tom', 'lucy']
f3(students, clazz='1904')
@decorate
def f4():
print('------------>f4')
f4()
装饰器离最近优先执行
'''
如果装饰器是多层的,谁距离函数最近就优先使用哪个装饰器
'''
# 装饰器
def zhuang1(func):
print('------->1 start')
def wrapper(*args, **kwargs):
func()
print('刷漆')
print('------->1 end')
return wrapper
def zhuang2(func):# func=house
print('------->2 start')
def wrapper(*args, **kwargs):
func()
print('铺地板,装门.....')
print('------->2 end')
return wrapper
@zhuang2
@zhuang1
def house(): # house = wrapper
print('我是毛坯房.....')
house()
------->1 start
------->1 end
------->2 start
------->2 end
我是毛坯房.....
刷漆
铺地板,装门.....
带参装饰器
# 装饰器带参数
'''
带参数的装饰器是三层的
最外层的函数负责接收装饰器参数
里面的内容还是原装饰器的内容
'''
def outer(a): # 第一层: 负责接收装饰器的参数
print('------------1 start')
def decorate(func): # 第二层 : 负责接收函数的
print('------------2 start')
def wrapper(*args, **kwargs): # 第三层 负责接收函数的参数
func(*args)
print("---->铺地砖{}块".format(a))
print('------------2 end')
return wrapper # 返出来的是:第三层
print('------------1 end')
return decorate # 返出来的是:第二层
@outer(10)
def house(time):
print('我{}日期拿到房子的钥匙,是毛坯房....'.format(time))
# @outer(100)
# def street():
# print('新修街道名字是:黑泉路')
house('2019-6-12')
# street()
# ------------1 start
# ------------1 end
# ------------2 start
# ------------2 end
# 我2019-6-12日期拿到房子的钥匙,是毛坯房....
# ---->铺地砖10块
综合装饰器示例
import time
islogin = False
#定义一个登录login方法
def login():
username = input('输入用户名:')
password = input('输入密码:')
if username == 'xks' and password == '11111111':
return True
else:
return False
#定义一个装饰器 进行付款验证
def login_required(func):
def wrapper(*args,**kwargs):
#修改全局的变量需要进行定义global
global islogin
print('付款准备阶段... ... ... ...')
# 验证用户是否登录
if islogin:
func(*args,**kwargs)
else:
#跳转到登录页面
print('用户未登录,无法付款... ... ...')
islogin = login()
print('islogin:',islogin)
return wrapper
@login_required
def pay(money):
print('正在付款,付款金额是:{}元'.format(money))
print('付款中')
time.sleep(2)
print('付款完成')
pay(10000)
pay(20000)
# 付款准备阶段... ... ... ...
# 用户未登录,无法付款... ... ...
# 输入用户名:xks
# 输入密码:11111111
# islogin: True
# 付款准备阶段... ... ... ...
# 正在付款,付款金额是:20000元
# 付款中
# 付款完成