函数进阶---作用域、闭包、装饰器
名称空间
名称空间指存放名字的地方
名称空间分为三种:
- locals:函数内部的名称空间,包括局部变量与形参
- globals:全局变量,函数模块定义所在模块的空间
- builtins 内置模块的名称空间
不同变量的作用域不同就是由这个变量的所在变名空间决定的
作用域:
全局范围:全局存活,在全局生效
局部范围:局部存活,在局部生效
查看作用域的方法:locals(),globals()
名称空间的查找顺序
LEGB查找顺序:locals-->enclosing function-->globals-->builtins - locals:指局部名称空间
- enclosing function:指外部嵌套函数的名称空间
- globals:全局变量,函数模块定义所在的名称空间
- builtins:内置模块的名称空间
闭包
闭包是指内部函数包含对外部作用域而非全局作用域的引用,即:A函数里再定义一个b函数(嵌套函数)而B函数里调了A函数的变量,而A函数返回值是B函数的引用,这样就构成了闭包
def fun():
name = 'ab'
def fun1():
print('fun1',name)
return fun1
a = fun()
a()
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
装饰器
什么是装饰器?
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:
- 不修改被装饰对象的源代码
- 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
程序员应该尊守封闭,开发原则!
- 封闭:已实现的功能代码块不应该被修改
- 开放:对现有功能的扩展开放
代码:
flag = False
def login(fun):
def ineer(*args,**kwargs):
username = 'alex'
password = '123'
global flag
if flag == False:
_username = input('user:').strip()
_passwd = input('passwd:').strip()
if _username == username and _passwd == password:
print('登陆成功')
flag = True
else:
print('登陆失败')
if flag == True:
return fun(*args,**kwargs)
return ineer
def home():
print("---首页----")
@login
def america():
#login() #执行前加上验证
print('用户已登陆,不需要验证')
print("----欧美专区----")
def japan():
print("----日韩专区----")
@login #想当于henan = login(henan)
def henan(style):
'''
:param style: 喜欢看什么类型的,就传进来
:return:
'''
#login() #执行前加上验证
print("----河南专区----")
henan('3p') #实际调用的是inner函数
america()