python学习第四天回顾(函数的对象,嵌套,名称空间与作用域,闭包,装饰器,迭代器)
| 一、函数对象 |
函数是第一类对象,具有属性(可用dir()查询),即函数可以当作数据传递
a:可以被引用
b: 可以当作参数传递
c: 返回值可以是函数
d: 可以当作容器类型的元素
函数引用的示例:
1 def foo(): 2 print('from foo') 3 4 func=foo 5 6 print(foo) #打印出的结果为foo的内存地址 7 print(func) #打印出的结果与print(foo)的一致,故func=foo是foo将它的内存地址赋值给了func变量 8 func() #func()就相当于调用foo函数在内存地址中所存放的内容,所以会将foo函数执行。
1 返回结果为: 2 <function foo at 0x00000230735F3E18> 3 <function foo at 0x00000230735F3E18> 4 from foo
函数当作参数引用的示例:
1 def foo(): 2 print('from foo') 3 4 def bar(func): 5 print(func) 6 func() 7 8 bar(foo) #函数调用的参数为foo对应foo函数的内存地址,传给func后即func=foo的内存地址
1 返回结果为: 2 <function foo at 0x00000188D7223E18> #func为foo的内存地址被打印出来 3 from foo #func()相当于执行foo()函数的内容
函数的返回值可以是函数示例:
1 def foo(): 2 print('from foo') 3 #定义foo函数 4 def bar(func): 5 return func 6 #定义bar函数,形参为func,并返回形参的值 7 f=bar(foo) 8 #调用bar()函数,并将实参foo传给bar函数的形参,赋值给f《实参foo为foo()函数的内存地址,f被赋值foo()函数的内存地址》 9 print(f) 10 #打印f 《即foo()函数的内存地址》 11 f() #调用f函数相当于调用foo()函数
1 返回值为: 2 <function foo at 0x000001ABABE83E18> 3 from foo
函数可以当作容器类型的元素 示例:
1 def foo(): #定义一个foo()函数 2 print('from foo') 3 dic={'func':foo} 4 #定义一个字典,字典的键为func,值为foo 5 print(dic['func']) 6 #打印dic字典func键,获取dic["func"]的值,结果为foo()函数的内存地址 7 dic['func']()#dic['func']就相当于foo()函数的内存地址,加()就可以调用foo()函数
1 返回值: 2 <function foo at 0x000002131B623E18> 3 from foo
应用示例:
1 #应用 2 3 # def select(sql): 4 # print('========>select') 5 # 6 # def insert(sql): 7 # print('========>add') 8 # 9 # def delete(sql): 10 # print('=======>delete') 11 # 12 # def update(sql): 13 # print('-=---->update') 14 # 15 # 16 # func_dic={ 17 # 'select':select, 18 # 'update':update, 19 # 'insert':insert, 20 # 'delete':delete 21 # } 22 # 23 # def main(): 24 # while True: 25 # sql = input('>>: ').strip() 26 # if not sql:continue 27 # l = sql.split() 28 # cmd=l[0] 29 # if cmd in func_dic: 30 # func_dic[cmd](l) 31 # 32 # main() 33 # def main(): 34 # sql = input('>>: ') 35 # l = sql.split() 36 # print(l) 37 # if l[0] == 'select': 38 # select(l) 39 # elif l[0] == 'insert': 40 # insert(l) 41 # elif l[0] == 'delete': 42 # delete(l) 43 # elif l[0] == 'update': 44 # update(l)
| 二、函数的嵌套 |
Python中允许在定义函数的时候,其他函数体内又包含另外一个函数的完整定义,这就是我们通常所说的嵌套定义。
函数的嵌套调用 示例:
1 def max(x,y): 2 return x if x > y else y 3 4 def max2(a,b,c,d): 5 res1=max(a,b) 6 res2=max(res1,c) 7 res3=max(res2,d) 8 return res3 9 10 print(max2(10,23,15,70)
1 返回结果为: 2 70 3 # 调用过程:max2将位置实参,10,23,15,70传值给max2()函数 4 #执行函数体中的内容,在函数体中有max(a,b),则调用max(x,y),进行比较并返回一个最大的值,依此类推将最终结果返回。
函数嵌套的定义 示例:
1 def f1(): 2 3 def f2(): 4 print('from f2') 5 def f3(): 6 print('from f3') 7 f3() 8 f2() 9 10 11 f1() #函数内定义函数即为函数的嵌套。
| 三、名称空间与作用域 |
名称空间分为三种:
内置名称空间:python内部定义的,即随着python解释器的启动而产生
内置名称空间相当于内置函数:
示例:
1 # print(sum) 2 # print(max) 3 # print(min) 4 5 # print(max([1,3,2])
1 还可以遍历一下内置函数有哪些: 2 import builtins 3 for i in dir(duiltins): 4 print(i) #dir函数可以查看内置函数的属性。
全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间内。
1 x=1 #定义变量x,为全局变量,没有在函数内所以为全局变量 2 3 def func(): #定义函数func(),没有在函数内所以为全局变量 4 money=2000 #在函数内定义money变量,局部变量只可以函数内使用 5 x=2 #在函数内定义x变量,局部变量只可以函数内使用 6 print('func') #打印func字符串 7 print(x) 8 print(func) 9 func() 10 print(money) 11 12 func() 13 print(x)
1 返回结果为: 2 1 #对应上面的print(x),因为变量x在文件里定义的而不是在函数里面,所以为全局变量 3 <function func at 0x00000267CDDDB950> #对应print(func),func函数为全局的名称,即在文件下执行,不调用函数,故打印func内存地址 4 func #调用func()函数,故执行func函数,打印func字符串 5 NameError:name"money" is not defined #定义的money变量是在函数中定义的,为局部变量,全局有没有,故报错。 6 func #调用func()函数,故执行func函数,打印func字符串
7 1 #对应上面的print(x),因为变量x在文件里定义的而不是在函数里面,所以为全局变量
局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束后解除绑定。
1 x=10000 2 def func(): 3 x=1 4 print(x) 5 def f1(): 6 pass 7 print(x) 8 func()
1 返回结果为: 2 10000 #打印的是全局变量中的x,即x=10000 3 1 #打印的是局部变量中的x,即x=1
<注意:名字的查找顺序:局部名称空间---》 全局名称空间---》 内置名称空间>
作用域:
1:全局作用域:内置名称空间,全局名称空间
2:局部作用域:局部名称空间
#查看全局作用域内的名字:gloabls()
#查看局部作用域内的名字:locals()
1 #globals()与locals()的使用方法 2 x=1000 3 def func(): 4 x=2 5 6 print(globals()) 7 8 print(locals()) 9 print(globals() is locals())
1 返回结果为: 2 {'__name__': '__main__', '__doc__': '\n作用域:\n 1. 全局作用域:内置名称空间,全局名层空间\n 2. 局部作用:局部名称空间\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001AC9BCAB278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/python17期/day4/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000001AC9BD7B950>} 3 {'__name__': '__main__', '__doc__': '\n作用域:\n 1. 全局作用域:内置名称空间,全局名层空间\n 2. 局部作用:局部名称空间\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001AC9BCAB278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/python17期/day4/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000001AC9BD7B950>} 4 True 5 #globals()与locals()在全局作用域下输出的结果一致,故为True
1 x=1000 2 def func(y): 3 x=2 4 print(locals()) 5 print(globals()) 6 7 func(1)
1 返回结果为: 2 {'x': 2, 'y': 1} #输出局部作用域的内容,即局部变量内的x=2,y=1,以字典的形式输出 3 {'__name__': '__main__', '__doc__': '\n作用域:\n 1. 全局作用域:内置名称空间,全局名层空间\n 2. 局部作用:局部名称空间\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E5C9BDB278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/python17期/day4/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000001E5C9CAB950>} 4 #输出全局变量的相关信息
《注意:
全局作用域:全局有效,在任何位置都能访问到,除非del删除,否则会一直存活到文件执行完毕。
局部作用域:局部有效,只在局部范围内调用,只在函数调用时才生效,调用结束就会释放。》
1 示例: 2 x=1 3 4 def f1(): 5 print(x) 6 7 def foo(): 8 print(x) 9 10 def f(x): 11 x=4 12 def f2(): 13 x=3 14 def f3(): 15 x=2 16 print(x) 17 18 f3() 19 f2() 20 21 f(4) 22 f1() 23 foo()
1 返回结果为: 2 2 #f3()函数内: x=2 x为局部变量 3 1 #x为全局变量 4 1 #x为全局变量
| 四、闭包 |
闭包函数:
定义在内部的函数
包含对外部作用域而非全局作用域的引用。
该内部函数就成为闭包函数
示例
1 def f1(): 2 x = 1 3 def f2(): 4 print(x) 5 6 return f2 7 8 f=f1() 9 print(f) 10 11 x=100000000000000000000000000 12 f()
1 返回结果为: 2 <function f1.<locals>.f2 at 0x000000000292B9D8> 3 1
闭包函数应用:惰性计算
1 from urllib.request import urlopen 2 3 def index(url): 4 def get(): 5 return urlopen(url).read()#返回urlopen函数的结果并读取 6 7 return get 8 9 oldboy=index('http://crm.oldboyedu.com') #调用index函数,将实参传给形参url,获得get函数的内存地址 10 11 print(oldboy) #oldboy变量即get函数的内存地址,若需要调用则需要加(),即oldboy()
# print(oldboy().decode('utf-8'))
# print(oldboy.__closure__[0].cell_contents) #闭包函数中必有__closure__属性,这条语句可以表示闭包函数中参数的值。
# res=urlopen('http://crm.oldboyedu.com').read()
#
# print(res.decode('utf-8'))
1 返回结果为: 2 <function index.<locals>.get at 0x0000000002E06048>
| 五、装饰器 |
装饰器:
修饰别人的工具,修饰添加功能,工具指的是函数。
修饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用对象。
为什么要用装饰器:
开放封闭原则:对修改是封闭的,对扩展是开放的(在原有函数基础上,用新的函数添加新的功能)
装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为期添加新功能。
1 装饰器示例: 2 import time #导入time函数 3 4 def timmer(func): #定义一个timmer()函数,形参为func,实参为index函数的内存地址。 5 def wrapper(*args,**kwargs): #定义一个wrapper()函数,形参为*args,**kwargs 6 start_time=time.time() #记录开始时间 7 res=func(*args,**kwargs) #执行func()函数即index()函数 8 stop_time=time.time() #记录结束时间 9 print('run time is %s' %(stop_time-start_time)) #打印出使用的时间(结束时间-开始时间) 10 return wrapper 11 12 @timmer #@timmer跟下方的index()函数一起使用,相当于timmer(index) 13 def index(): 14 15 time.sleep(3) 16 print('welcome to index') 17 18 index() #执行index()函数相当于wrapper函数(执行index函数时会先调用装饰器@timmer,执行timmer(func)函数的内容,执行wrapper函数,
#开始记录时间,执行func()函数,该func对应timmer(func)中的func,加()后即index()函数。执行index()函数的内容,记录结束时间,打印出使用的时间)
1 返回结果为: 2 welcome to index 3 run time is 3.000171661376953
1 #流程分析 2 # import time 3 # def timmer(func): 4 # def wrapper(): 5 # start_time=time.time() 6 # func() 7 # stop_time=time.time() 8 # print('run time is %s' %(stop_time-start_time)) 9 # return wrapper 10 # 11 # @timmer #index=timmer(index) 12 # def index(): 13 # time.sleep(3) 14 # print('welcome to index') 15 # 16 # 17 # index() #wrapper()
1 #装饰器,有参数的 2 # import time 3 # def timmer(func): 4 # def wrapper(*args,**kwargs): 5 # start_time=time.time() 6 # func(*args,**kwargs) 7 # stop_time=time.time() 8 # print("run time is %s" % (stop_time-start_time)) 9 # return args[0] 10 # return wrapper 11 # 12 # @timmer # index=timmer(index) 13 # def index(a): 14 # time.sleep(3) 15 # print("welcome to index") 16 # 17 # print(res)
1 #用装饰器写用户登录验证 2 # def user(auth): 3 # def login(*args,**kwargs): 4 # name = input("input name:") 5 # pwd = input("input pwd:") 6 # if name=="egon" and pwd == "123123": 7 # auth(*args,**kwargs) 8 # print("login sucess!") 9 # else: 10 # print ("login fail!") 11 # return login 12 # 13 # @user 14 # def user_input(): 15 # print("login sucessed!") 16 # 17 # user_input()
1 #========================有参装饰器 2 # import time 3 # def timmer(func): 4 # def wrapper(*args,**kwargs): 5 # print('====>timmer.wrapper') 6 # start_time=time.time() 7 # res=func(*args,**kwargs) #auth_wrapper 8 # stop_time=time.time() 9 # print('run time is %s' %(stop_time-start_time)) 10 # return res 11 # return wrapper 12 # 13 # 14 # 15 # login_user={'user':None,'status':False} 16 # def auth(driver='file'): 17 # def auth2(func): 18 # def wrapper(*args,**kwargs): 19 # print('=======>auth.wrapper') 20 # time.sleep(5) 21 # if driver == 'file': 22 # if login_user['user'] and login_user['status']: 23 # res=func(*args,**kwargs) 24 # return res 25 # else: 26 # name=input('>>: ') 27 # password=input('>>: ') 28 # if name == 'egon' and password == '123': 29 # login_user['user']='egon' 30 # login_user['status']=True 31 # print('\033[45mlogin successful\033[0m') 32 # res=func(*args,**kwargs) 33 # return res 34 # else: 35 # print('\033[45mlogin err\033[0m') 36 # elif driver == 'ldap': 37 # print('==========ldap的认证') 38 # elif driver == 'mysql': 39 # print('==========mysql的认证') 40 # return func(*args,**kwargs) 41 # else: 42 # print('=========未知的认证来源') 43 # return wrapper 44 # return auth2 45 # 46 # 47 # @auth('file') #@auth2====>index=auth2(index)===>index=auth_wrapper 48 # @timmer #index=timmer(auth_wrapper) #index=timmer_wrapper 49 # def index(): 50 # time.sleep(3) 51 # print('welcome to index page') 52 # @auth(driver='mysql') 53 # def home(name): 54 # print('%s welcome to home page' %name) 55 # index() #timmer_wrapper() 56 # home('egon') #wrapper('egon')
| 六、迭代器 |
迭代器:
迭代的概念:重复---上一次迭代的结果为下一次迭代的初始值
重复的过程称为迭代,每一次重复即一次迭代,并每次迭代的结果为下一次迭代的初始值。
1 # while True: #只满足重复,因而不是迭代 2 # print('====>') 3 《不满足迭代的条件》
1 #下面才为迭代 2 # l = [1, 2, 3] 3 # count = 0 4 # while count < len(l): 5 # print('====>', l[count]) 6 # count += 1 7 # 《以上为列表的迭代》 8 # l = (1, 2, 3) 9 # count = 0 10 # while count < len(l): 11 # print('====>', l[count]) 12 # count += 1 13 #《以上为元组的迭代》 14 # s='hello' 15 # count = 0 16 # while count < len(s): 17 # print('====>', s[count]) 18 # count += 1 19 # 《以上为字符串的迭代》
为什么要有迭代器?对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
可迭代的对象:内置__iter__方法的,都是可迭代的对象
1 # [1,2].__iter__() 2 # 'hello'.__iter__() 3 # (1,2).__iter__() 4 # 5 # {'a':1,'b':2}.__iter__() 6 # {1,2,3}.__iter__()
迭代器:执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法
1 i=[1,2,3].__iter__() #列表[1,2,3]调用__iter__方法后即为迭代器 2 3 print(i) #i为列表迭代器的内存地址 4 5 print(i.__next__()) #迭代器i调用next方法,并打印 6 print(i.__next__()) 7 print(i.__next__()) 8 print(i.__next__()) #抛出异常:StopIteration
返回结果为: <list_iterator object at 0x00000000028F9F28> 1 2 3 print(i.__next__()) #抛出异常:StopIteration
1 i={'a':1,'b':2,'c':3}.__iter__() 2 3 print(i.__next__()) 4 print(i.__next__()) 5 print(i.__next__()) 6 7 返回结果为: #字典i的key 8 a 9 b 10 c
1 dic={'a':1,'b':2,'c':3} 2 i=dic.__iter__() 3 while True: 4 try: 5 key=i.__next__() 6 print(dic[key]) 7 except StopIteration: 8 break 9 10 返回结果为: 返回结果为字典的values 11 1 12 2 13 3
如何判断一个对象是可迭代的对象,还是迭代器对象
1 from collections import Iterable,Iterator 2 3 'abc'.__iter__() 4 ().__iter__() 5 [].__iter__() 6 {'a':1}.__iter__() 7 {1,2}.__iter__() 8 9 f=open('a.txt','w') 10 f.__iter__() 11 12 13 # 下列数据类型都是可迭代的对象 14 print(isinstance('abc',Iterable)) 15 print(isinstance([],Iterable)) 16 print(isinstance((),Iterable)) 17 print(isinstance({'a':1},Iterable)) 18 print(isinstance({1,2},Iterable)) 19 print(isinstance(f,Iterable)) 20 print("Iterable") 21 22 23 # 只有文件是迭代器对象 24 print(isinstance('abc',Iterator)) 25 print(isinstance([],Iterator)) 26 print(isinstance((),Iterator)) 27 print(isinstance({'a':1},Iterator)) 28 print(isinstance({1,2},Iterator)) 29 print(isinstance(f,Iterator)) 30 print("Iterator")
1 返回结果为: 2 True # 3 True 4 True 5 True 6 True 7 True 8 Iterable #字符串,列表,元组,字典,集合,文件都是可迭代对象 9 False 10 False 11 False 12 False 13 False 14 True 15 Iterator #只有文件是迭代器对象。
《注意:
可迭代对象:只有__iter__方法,执行该方法后得到迭代器对象
迭代协议:
对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是其本身。
对象有__next__,》
1 f=open('a.txt','w') 2 f1=f.__iter__() 3 4 print(f) 5 print(f1) 6 print(f is f1) 7 8 返回结果为: 9 <_io.TextIOWrapper name='a.txt' mode='w' encoding='cp936'> #f的打印结果 10 <_io.TextIOWrapper name='a.txt' mode='w' encoding='cp936'> #f1的打印结果 11 True #f与f1对比的结果

浙公网安备 33010602011771号