函数之命名空间、作用域、闭包、装饰器四剑客。

# 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的前提下,为被装饰对象添加上新功能
 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")
装饰器的应用

 

  

 

posted @ 2018-03-26 11:06  小狗子  阅读(275)  评论(0编辑  收藏  举报