1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
1.名称空间
 
python有三种名称空间
内置名称空间: 随着python解释器的启动而产生
print(sum)
print(max)
 
全局名称空间: 文件的执行会产生全局名称空间,指的是文件级别的定义名字都会放入该空间
= 11
if == 11:
    print(x)
 
局部名称空间: 调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束时解绑
= 1000
def foo():
    = 1
    print(x)
foo()
print(x)
 
作用域:
    1.全局作用域: 内置名称空间,全局名称空间,全局有效,在任何位置都能被访问到,
    除非del删除,否则存活到文件结束。
    2.局部作用域: 局部名称空间,局部有效,只能在局部范围调用,调用结束失效。
 
名字的查找顺序: 局部名称空间-->全局名称空间-->内置名称空间
= 1000
def func():
    = 2
    print(locals())    #locals()查看局部作用域内的名字
print(globals())    #globals()查看全局作用域内的名字
 
 
2.函数对象
    1.可以被引用
    2.可以当作参数传递
    3.返回值可以是函数
    4.可以当作容器类型的元素
     
 例子:
     def foo():
         print("from foo")
     func = foo
     print(foo)
     print(func)
     foo()
     func()
      
     def foo():
         print("from foo")
     def bar(func):
         print(func)
         func()
     bar(foo)
      
     def foo():
         print("from foo")
     dic = {'func': foo}
     print(dic['func'])
     dic['func']()
      
      
      
3.闭包函数
    闭包:
      1.定义在内部函数
      2.包含对外部作用域而非全局作用域的引用
  该内部函数就称作闭包函数
  例子:
  def f1():
    = 1
    def f2():     #f2称作闭包函数
      print(x)
    return f2
  = f1()
  print(f)   #打印f2函数的内存地址
  f()    #打印1
  
   例子:
   from urllib.request import urlopen
   def index(url):
       def get():
           return urlopen(url).read()
       return get
   oldboy = index('http://www.baidu.com')
   print(oldboy().decode('utf-8'))
   print(oldboy.__closure__[0].cell_contents)    #打印外部引用而非全局引用对象
    
4.装饰器
    修饰其他对象的工具,修饰添加功能,工具指的是函数。
    装饰器本身是任何可调用对象,被装饰的对象也可以是任何可调用的对象。
     
    为什么要用装饰器?
    开放封闭原则,对修改是封闭的,对扩展是开放的。
    装饰器就是为了在不修改被装饰对象源代码以及调用方式的前提下,为其添加新功能
     
    装饰器相当于闭包的实现
     
    例子:
    import time
    def timmer(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            stop_time = time.time()
            print("run time is {0}".format(stop_time - start_time))
        return wrapper
         
    @timmer        #相当于index = timmer(index)
    def index():
        time.sleep(3)
        print("welcome to index")
        return 1
         
    index()    #其实相当于执行了timmer(index)
     
    例子:
    import time
    def timmer(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            stop_time = time.time()
            print("run time is {0}".format(stop_time - start_time))
        return wrapper
         
    def index():
        time.sleep(3)
        print("welcome to index")
     
    = timmer(index)
    print(f)
    f()        #f()<=====>wrapper()
     
     
    认证用户登录
    login_user = {'user'None'status'False}
    def auth(func):
        def wrapper(*args, **kwargs):
            if login_user['user'and login_user['status']:
                res = func(*args, **kwargs)
                return res
            else:
                name = input("请输入姓名:")
                passwd = input("请输入密码:")
                if name == "hyh" and passwd == "123":
                    login_user['user'= "hyh"
                    login_user['status'= True
                    print("\033[45mlogin successful\033[0m")
                    res = func(*args, **kwargs)
                    return res
                else:
                    print("\033[45mlogin err\033[0m")
        return wrapper
         
   @auth
   def index():
       print("welcome to index page")
        
   @auth
   def home(name):
       print("%s welcome to home page" % (name)) 
        
   index()
   home("hyh")
    
5.迭代器
    迭代器的概念: 重复上一次迭代的结果为下一次迭代的初始值,重复的过程称为迭代,
    每次重复即一次迭代
     
    为什么要有迭代器?
    对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
     
    可迭代对象: 内置__iter__方法的都是可迭代对象
    [1,2].__iter__()
    'hello'.__iter__()
    (1,2).__iter__()
    {"a":1"b"2}.__iter__()
    {1,2,3}.__iter__()
     
    迭代器: 执行__iter__()方法,得到的结果就是迭代器,迭代器有__next__()方法
    = [1,2,3].__iter__()
    print(i.__next__())        #打印1
    print(i.__next__())        #打印2
    print(i.__next__())        #打印3
    print(i.__next__())    #抛出异常
     
    i__iter__() <==>iter(i)
    i__next__() <==>next(i)
     
    如何判断一个对象是可迭代对象,还是迭代器对象
    from collections import Iterable, Iterator
    print(isinstance('abc',Iterable))
    print(isinstance([],Iterable))
    print(isinstance((),Iterable))
    print(isinstance({'a':1},Iterable))
    print(isinstance({1,2},Iterable))
    f=open('a.txt','w')
    f.__iter__()
    print(isinstance(f,Iterable))    #只有文件是迭代器对象
     
    可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象
    迭代协议:
        对象有__next__
        对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
         
    迭代器的优点和缺点
        优点:
            1.提供了一种不依赖下标的迭代方式
            2.就跌迭代器本身来说,更节省内存
 
        缺点:
            1. 无法获取迭代器对象的长度
            2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退