目录:
- 函数补充进阶
- 函数对象
- 函数的嵌套
- 名称空间与作用域
- 闭包函数
- 函数之装饰器
- 函数之迭代器
- 函数之生成器
- 内置函数
一、函数补充进阶
1、函数对象:
函数是第一类对象,即函数可以当作数据传递,它的应用形式也被称为高阶函数,函数的特性如下:
a. 可以被引用
1 # def foo(): 2 # print('from foo') 3 # 4 # func = foo 5 # print(foo) # 不加括号为foo函数的内存地址 6 # print(func) # func指向foo内存地址 7 # func() # foo内存地址,加()执行 8 ''' 9 结果: 10 <function foo at 0x0000007D79483E18> 11 <function foo at 0x0000007D79483E18> 12 from foo 13 '''
b. 可以当作参数传递
1 # def foo(): 2 # print('from foo') 3 # 4 # def bar(func): 5 # print(func) 6 # func() 7 # 8 # bar(foo) # foo函数内存地址被当作参数传递到bar函数中,并调用 9 10 ''' 11 结果: 12 <function foo at 0x00000049CC9A3E18> 13 from foo 14 '''
c. 返回值可以是函数
1 # def foo(): 2 # print('from foo') 3 # 4 # def bar(func): 5 # return func 6 # 7 # f = bar(foo) # 去到返回值foo内存地址 8 # print(f) 9 # f() # 调用 10 11 ''' 12 结果: 13 <function foo at 0x000000F005753E18> 14 from foo 15 '''
d. 应用
1 # def select(sql): 2 # print('----〉select:%s' % sql) 3 # 4 # def insert(sql): 5 # print('----〉insert:%s' % sql) 6 # 7 # def update(sql): 8 # print('----〉update:%s' % sql) 9 # 10 # def delect(sql): 11 # print('----〉delect:%s' % sql) 12 # 13 # sql_dic = { 14 # 'select':select, 15 # 'delect':delect, 16 # 'insert':insert, 17 # 'update':update 18 # } 19 # def main(): 20 # while True: 21 # sql = input('sql>>>').strip() 22 # if not sql:continue 23 # sql_l = sql.split(' ') 24 # if sql_l[0] in sql_dic: 25 # sql_dic[sql_l[0]](sql_l) 26 # 27 # main() 28 ''' 29 结果: 30 sql>>>select * form fafafa 31 ----〉select:['select', '*', 'form', 'fafafa'] 32 sql>>>insert * faormafa faf a 33 ----〉insert:['insert', '*', 'faormafa', '', 'faf', 'a'] 34 sql>>> 35 '''
2、函数的嵌套
闭包函数基础
a. 函数的嵌套定义: 函数的嵌套定义:顾名思义就是函数里面,套函数。应用如闭包、装饰器
1 ''' 2 函数的嵌套定义:顾名思义就是函数里面,套函数。应用如闭包、装饰器 3 ''' 4 # 层层调用,层层执行 5 # def f1(): 6 # def f2(): 7 # print('from f2') 8 # def f3(): 9 # print('from f3') 10 # f3() 11 # f2() 12 # f1() 13 ''' 14 结果: 15 from f2 16 from f3 17 '''
b. 函数的嵌套调用:属于面向过程(分子原子级操作),细分问题
1 ''' 2 函数的嵌套调用 3 ''' 4 # 判断两个数数字的大小 5 # def max2(x,y): 6 # return x if x > y else y 7 8 # 判断4个数大小,调用上面的函数 9 # def max4(a,b,c,d): 10 # res1=max2(a,b) 11 # res2=max2(res1,c) 12 # res3=max2(res2,d) 13 # return res3 14 # 15 # print(max4(10,99,31,22)) 16 ''' 17 结果: 18 99 19 '''
3、名称空间与作用域
a. 名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象
1 ''' 2 1、名称空间定义(namespace): 名字绑定值时,名字与值得对应关系的存放位置为名称空间 3 定义名字的方法 4 ''' 5 # a.导入模块 6 # import time 7 # b.变量赋值 8 # name='egon' 9 # c.函数定义 10 # def func(): 11 # pass 12 # d.类定义(面向对象) 13 # class Foo: 14 # pass
b. 名称空间的分类:
1.内置名称空间:随着python解释器的启动而产生
1 # print(sum) 2 # print(max) 3 # print(min) 4 # 等等,python已启动,初始定义的功能。 5 ''' 6 结果: 7 <built-in function sum> 8 <built-in function max> 9 <built-in function min> 10 ''' 11 12 # print(max([1,2,3])) 13 14 # builtins dir()函数接受模块名作为参数,返回一个排好序的字符串列表,内容是一个模块里定义过的名字。 15 # import builtins 16 # dir 对象的内建名称空间 17 # for i in dir(builtins): 18 # print(i)
2.全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间
1 # 不在函数和类,定义变量 2 # x=1 3 # if x ==1 : 4 # y=2 5 6 # 不在函数和类,导入模块 7 # import time 8 9 # 不在函数和类,定义变量 10 # name='egon' 11 12 # 不在类中,定义的函数名 13 # def func(): 14 # pass 15 16 # 不在类中,定义类名 17 # class Foo: 18 # pass 19 20 # x=1 21 # def func(): 22 # money=2000 23 # x=2 24 # print(func) 25 # # 局部x=2 没有调到 26 # print(x) 27 # # 取到内存地址 28 # print(func) 29 # # 执行函数可以调到全局变量 30 # func() 31 # # print(money) # money属于局部变量,调用不了
3.局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定
1 1# x=10000 2 # def func(): 3 # x = 1 局部变量 4 # x=1 5 # def f1(): 6 # pass
c. 作用域:为名称空间的具体应用。他们之间的关系,如下对应:
1.全局作用域:内置名称空间,全局名层空间
2.局部作用:局部名称空间
d. 作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间
1 ''' 2 # 后生效 3 # x=1 4 # def func(): 5 # # 优先生效 6 # x = 2 7 # print(x) 8 # sum = 123123 9 # print(sum) 10 # func() 11 ''' 12 结果: 13 2 14 123123 15 ''' 16 17 # x = 1 18 # def func(): 19 # x=2 20 # 21 # func() 22 # 23 # print(x) 24 ''' 25 结果: 26 1 27 '''
1.查看全局作用域内的名字:gloabls()
2.查看局局作用域内的名字:locals()
1 ''' 2 查看全局作用域内的名字:gloabls() 3 查看局部作用域内的名字:locals() 4 ''' 5 x=1000 6 def func(): 7 x=2 8 # 全局作用域内 9 print(globals()) 10 # 局部作用域 11 print(locals()) 12 func() 13 # 全局作用域内 14 print(globals()) 15 # 局部作用域 16 print(locals()) 17 # 在全局环境中,locals()和globals()是一样的,但是在局部环境中,就不一样了 18 print(globals() is locals()) 19 ''' 20 结果: 21 {'__name__': '__main__', '__doc__': ' 名称空间与作用域 1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象 2、名称空间的分类: 内置名称空间:随着python解释器的启动而产生 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定 3、作用域:为名称空间的具体应用。他们之间的关系,如下对应: 全局作用域:内置名称空间,全局名层空间 局部作用:局部名称空间 4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间 查看全局作用域内的名字:gloabls() 查看局局作用域内的名字:locals() ', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000D9A5DCB160>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/old_boy/old_boy_17_04/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000000D9A5B03E18>} 22 {'x': 2} 23 {'__name__': '__main__', '__doc__': ' 名称空间与作用域 1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象 2、名称空间的分类: 内置名称空间:随着python解释器的启动而产生 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定 3、作用域:为名称空间的具体应用。他们之间的关系,如下对应: 全局作用域:内置名称空间,全局名层空间 局部作用:局部名称空间 4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间 查看全局作用域内的名字:gloabls() 查看局局作用域内的名字:locals() ', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000D9A5DCB160>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/old_boy/old_boy_17_04/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000000D9A5B03E18>} 24 {'__name__': '__main__', '__doc__': ' 名称空间与作用域 1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象 2、名称空间的分类: 内置名称空间:随着python解释器的启动而产生 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定 3、作用域:为名称空间的具体应用。他们之间的关系,如下对应: 全局作用域:内置名称空间,全局名层空间 局部作用:局部名称空间 4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间 查看全局作用域内的名字:gloabls() 查看局局作用域内的名字:locals() ', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000D9A5DCB160>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/old_boy/old_boy_17_04/名称空间与作用域.py', '__cached__': None, 'x': 1000, 'func': <function func at 0x000000D9A5B03E18>} 25 True 26 '''
4、闭包函数
函数嵌套的一种方式,必须遵守以下规则:
a. 定义在内部函数
b. 包含对外部作用域而非全局作用域的引用,该内部函数就成为闭包函数
1 # 定义实例,对象隐藏,全局不可见 2 # def f1(): 3 # # x内部隐藏,全局不可见 4 # x = 1 5 # def f2(): 6 # print(x) 7 # 8 # return f2 9 # 10 # f=f1() 11 # # print(f) 12 # # x因为隐藏,所以全局作用域无效 13 # x=100000000000000000000000000 14 # f() 15 ''' 16 结果: 17 1 18 '''
闭包应用:惰性计算
1 # 爬网页,老式方法 2 # res=urlopen('http://crm.oldboyedu.com').read() 3 # print(res.decode('utf-8')) 4 # from urllib.request import urlopen 5 6 # def index(url): 7 # def get(): 8 # return urlopen(url).read() 9 # return get 10 11 # 存在内存里 12 # oldboy=index('http://crm.oldboyedu.com') 13 # 什么时候想用,什么时候用 14 # print(oldboy().decode('utf-8')) 15 16 # 闭包函数相对与普通函数会多出一个__closure__的属性,里面定义了一个元组用于存放所有的cell对象, 17 # 每个cell对象一一保存了这个闭包中所有的外部变量 18 # print(oldboy.__closure__[0].cell_contents) 19 20 21 22 23 24 # def f1(): 25 # x = 1 26 # y = 2 27 # def f2(): 28 # print(x,y) 29 # return f2 30 # 31 # a = f1() 32 # # a() 33 # print(a.__closure__[1].cell_contents) 34 ''' 35 结果: 36 2 37 '''
二、函数之装饰器
装饰器:修饰别人的工具,修饰添加功能,工具指的是函数
装饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用对象
为什么要用装饰器?
a. 开放封闭原则:对修改是封闭的,对扩展是开放的
b. 装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为期添加新功能
1、装饰器的基本写法
1 ''' 2 1、装饰器的基本写法 3 ''' 4 # import time 5 # 6 # def timmer(func): 7 # def wrapper(): 8 # # 在运行函数前执行,time.time()为当前时间(格林威治时间1970到现在的秒数) 9 # start_time = time.time() 10 # # 被装饰函数执行,没有返回值,默认为 11 # res = func() 12 # # 在函数运行后执行 13 # stop_time = time.time() 14 # print('run time is %s' %(stop_time-start_time)) 15 # return wrapper 16 # 17 # @timmer # index = timmer(index) 18 # def index(): 19 # time.sleep(3) 20 # print('welcome to index') 21 # 22 # index() # wrapper(index) ---> index() 23 ''' 24 结果: 25 welcome to index 26 run time is 3.000379800796509 27 '''
2、多实例添加,及传参数函数
1 ''' 2 2、多实例添加,及传参数函数 3 ''' 4 # import time 5 # def timmer(func): 6 # # 传递参数,保证通用性,应为可变长参数(*args,**kwargs),可接受所有类型的实参 7 # def wrapper(*args,**kwargs): 8 # start_time=time.time() 9 # # 传递参数,保证通用性,应为可变长参数(*args,**kwargs),可接受所有类型的实参 10 # # 有返回值,存值 11 # res=func(*args,**kwargs) 12 # stop_time=time.time() 13 # print('run time is %s' %(stop_time-start_time)) 14 # # 有返回值,返回 15 # return res 16 # return wrapper 17 # 18 # @timmer #index=timmer(index) 19 # def index(): 20 # time.sleep(3) 21 # print('welcome to index') 22 # # 有返回值,定义 23 # return 1 24 # 25 # #再次调用指需要加@timmer 26 # @timmer 27 # def foo(name): 28 # time.sleep(1) 29 # print('from foo') 30 # 31 # # 有返回值,传值打印 32 # res=index() #wrapper() 33 # print(res) 34 # 35 # res1=foo('shuyang') #res1=wrapper('egon') 36 # print(res1) 37 ''' 38 运行结果: 39 welcome to index 40 run time is 3.000380039215088 41 1 42 from foo 43 run time is 1.0001308917999268 44 None 45 '''
3、登录权限,一次登录,多次使用
1 ''' 2 3、登录权限,一次登录,多次使用 3 ''' 4 # 全局,记录用户状态 5 # login_user={'user':None,'status':False} 6 # def auth(func): 7 # def wrapper(*args,**kwargs): 8 # # 判断用户状态,有直接返回结果 9 # if login_user['user'] and login_user['status']: 10 # res=func(*args,**kwargs) 11 # return res 12 # # 否则,继续 13 # else: 14 # name=input('name: ') 15 # password=input('passwd: ') 16 # if name == 'shuyang' and password == '123': 17 # login_user['user']='shuyang' 18 # login_user['status']=True 19 # print('