函数之命名空间、作用域、闭包、装饰器四剑客。
# 1.三元运算 # name=1 if 1>2 else 3 # print(name) # 2.命名空间 # 全局命名空间:创建的存储“变量名与值的关系”的空间叫做全局命名空间 # 局部命名空间:在【函数】的运行中开辟的临时的空间叫做局部命名空间 # 内置命名空间:内置命名空间中存放了python解释器为我们提供的名字: # input,print,str,list,tuple... 它们都是我们熟悉的,拿过来就可以用的方法。 # 2.1命名空间的加载顺序: # python解释器先启动,因而首先加载的是:内置名称空间 #执行test.py文件,然后以文件为基础,加载全局名称空间 #在执行文件的过程中如果调用函数,则临时产生局部名称空间 # 3.1三种命名空间之间的使用顺序: # 3.1.全局的不能使用局部的 # 3.2.局部的可以使用全局的 # 4.作用域:作用的范围(作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关) # 4.1.首先作用域与命名空间是密不可分的 # 4.2 作用域分为两种: # 1.全局作用域:全局的命名空间与内置命名空间都属于全局范围,在整个文件的任意位置都能被引用,全局有效 # 2.局部作用域:局部命名空间,只能在局部范围内生效 # 4.3以全局的角度分析:使用名称的时候如果全局有则使用全局的,没有使用内置的,但全局的不能使用局部的 # 4.4 作用域的作用:为函数内的局部变量不受全局的影响 # 4.5查看作用域:globals(),locals() # LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ # locals 是函数内的名字空间,包括局部变量和形参 # enclosing 外部嵌套函数的名字空间(闭包中常见) # globals 全局变量,函数定义所在模块的名字空间 # builtins 内置模块的名字空间 #5.闭包函数: #内部函数 包含对外部作用域 而非全局作用域的引用 def outer(): name="alex" def inner(): print(name) #内部嵌套函数 包含了多外部函数outer的变量的引用 不是全局变量! return inner def counter(): n = 0 def incr(): nonlocal n # nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。 x = n n += 1 return x return incr c = counter() print(c()) #每次调用的时候counter 都会加一n 因为在内部inrc函数中声明n引用counter的n print(c()) print(c()) print("q", c.__closure__[0].cell_contents) # 查看闭包的元素 # 5.2闭包的意义与应用: # 闭包的意义: # 返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域, # 这使得,该函数无论在何处调用, # 优先使用自己外层包裹的作用域 from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu = index('http://www.baidu.com') #调用内部get之前就把url确定 # print(baidu().decode('utf-8')) #执行 打开index 下刚定义的局部变量url
6.0 装饰器 装饰器就是闭包函数的一种应用场景 为啥要用装饰器:开放封闭原则:对修改封闭,对扩展开放 6.1 何为装饰器: 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。 强调装饰器的原则: 1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式 装饰器的目标: 在遵循1和2的前提下,为被装饰对象添加上新功能
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 status_flag=False 2 3 4 def login(func): #把被装饰的函数当做参数传进来 5 6 def inner(*args,**kwargs): 7 global status_flag 8 _name = "alex" #进行验证 9 _passwd="123" 10 if status_flag == False: 11 user = input("user>:") 12 pwd = input("pwd>:") 13 if user==_name and pwd == _passwd: 14 status_flag=True 15 print("ok") #通过就执行此函数,并且把内部的函数 的内存地址返回给login 16 func(*args,**kwargs) 17 else: 18 print("erro!") 19 elif status_flag: 20 func(*args,**kwargs) 21 return inner #返回嵌套函数的内存地址给外层 外层被调用的时候才执行 22 @login #henan[返回新的河南的内存地址,只有调用才执行]=login(hanne(传进去的老的河南)) 23 def henan(name): 24 print(name) 25 print("欢迎进入河南专区".center(50, "*")) 26 @login 27 def hangzhou(): #杭州默认不加参数 调用的时候也不可以加,如果加参数,这样调用的时候才加参数 28 print("欢迎进入杭州专区".center(50, "*")) 29 30 31 print("装饰器进阶版".center(100, "*")) 32 33 #*************************************************************************************** 34 35 36 37 status_flag = False 38 39 def login(auth_type): # 接收装饰器函数的参数 40 41 def outer(func): # 把被装饰的函数当做参数传进来 42 43 def inner(*args, **kwargs): 44 global status_flag 45 _name = "alex" # 进行验证 46 _passwd = "123" 47 if status_flag == False: 48 user = input("user>:") 49 pwd = input("pwd>:") 50 if user == _name and pwd == _passwd: 51 status_flag = True 52 print("ok") # 通过就执行此函数,并且把内部的函数 的内存地址返回给login 53 func(*args, **kwargs) 54 else: 55 print("erro!") 56 elif status_flag: 57 func(*args, **kwargs) 58 59 return inner # 返回嵌套函数的内存地址给外层 外层被调用的时候才执行 60 61 return outer 62 63 64 # 在调用login的时候自动传入参数。 65 66 @login('aa') 67 def henan(name): 68 print(name) 69 print("欢迎进入河南专区".center(50, "*")) 70 71 72 @login("wx") # login("wx")(henan) 没执行之前其实已经做了这个转变 73 def hangzhou(): 74 print("欢迎进入杭州专区".center(50, "*")) 75 76 77 # hangzhou() #函数本身没有加参数,则调用也不能加 78 henan("sp")