python函数、装饰器、迭代器、生成器
目录:
- 函数补充进阶
- 函数对象
- 函数的嵌套
- 名称空间与作用域
- 闭包函数
- 函数之装饰器
- 函数之迭代器
- 函数之生成器
- 内置函数
一、函数补充进阶
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 # 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__': '\n名称空间与作用域\n1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象\n2、名称空间的分类: \n 内置名称空间:随着python解释器的启动而产生\n 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间\n 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定\n3、作用域:为名称空间的具体应用。他们之间的关系,如下对应:\n 全局作用域:内置名称空间,全局名层空间\n 局部作用:局部名称空间\n4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间\n 查看全局作用域内的名字:gloabls()\n 查看局局作用域内的名字:locals()\n', '__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__': '\n名称空间与作用域\n1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象\n2、名称空间的分类: \n 内置名称空间:随着python解释器的启动而产生\n 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间\n 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定\n3、作用域:为名称空间的具体应用。他们之间的关系,如下对应:\n 全局作用域:内置名称空间,全局名层空间\n 局部作用:局部名称空间\n4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间\n 查看全局作用域内的名字:gloabls()\n 查看局局作用域内的名字:locals()\n', '__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__': '\n名称空间与作用域\n1、名称空间定义(namespace): 名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象\n2、名称空间的分类: \n 内置名称空间:随着python解释器的启动而产生\n 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入改空间\n 局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定\n3、作用域:为名称空间的具体应用。他们之间的关系,如下对应:\n 全局作用域:内置名称空间,全局名层空间\n 局部作用:局部名称空间\n4、作用于的优先级顺序:局部名称空间---》全局名层空间---》内置名称空间\n 查看全局作用域内的名字:gloabls()\n 查看局局作用域内的名字:locals()\n', '__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('\033[45mlogin successful\033[0m') 20 # res=func(*args,**kwargs) 21 # return res 22 # else: 23 # print('\033[45mlogin err\033[0m') 24 # return wrapper 25 # 26 # @auth 27 # def index(): 28 # print('welcome to index page') 29 # @auth 30 # def home(name): 31 # print('%s welcome to home page' %name) 32 # index() 33 # home('shuyang') 34 35 ''' 36 结果: 37 name: shuyang 38 passwd: 123 39 login successful 40 welcome to index page 41 shuyang welcome to home page 42 '''
4、多装饰器,执行顺序
1 ''' 2 4、多装饰器,执行顺序 3 ''' 4 # import time 5 # def timmer(func): 6 # def wrapper(*args,**kwargs): 7 # print('timmer--->wrapper') 8 # start_time=time.time() 9 # res=func(*args,**kwargs) 10 # stop_time=time.time() 11 # print('run time is %s' %(stop_time-start_time)) 12 # return res 13 # return wrapper 14 # 15 # login_user={'user':None,'status':False} 16 # def auth(func): 17 # def wrapper(*args,**kwargs): 18 # print('auth--->wrapper') 19 # if login_user['user'] and login_user['status']: 20 # res=func(*args,**kwargs) 21 # return res 22 # else: 23 # name=input('name: ') 24 # password=input('pwd: ') 25 # if name == 'shuyang' and password == '123': 26 # login_user['user']='shuyang' 27 # login_user['status']=True 28 # print('\033[45mlogin successful\033[0m') 29 # res=func(*args,**kwargs) 30 # return res 31 # else: 32 # print('\033[45mlogin err\033[0m') 33 # return wrapper 34 # 35 # # 顺序执行 36 # @auth # timmer = auth--->wrapper--->timmer 37 # @timmer # index = auth--->wrapper--->timmer--->wrapper(index) 38 # def index(): 39 # time.sleep(3) 40 # print('welcome to index page') 41 # 42 # # 顺序执行,调转则timmer包含auth增加了程序执行时间 43 # @timmer # auth = timmer--->wrapper--->auth 44 # @auth # home = timmer--->wrapper--->auth---->wrapper(home) 45 # def home(name): 46 # time.sleep(3) 47 # print('%s welcome to home page' %name) 48 # index() 49 # home('shuyang') 50 ''' 51 结果: 52 auth--->wrapper 53 name: shuyang 54 pwd: 123 55 login successful 56 timmer--->wrapper 57 welcome to index page 58 run time is 3.000378131866455 59 timmer--->wrapper 60 auth--->wrapper 61 shuyang welcome to home page 62 run time is 3.000382423400879 63 '''
5、有参装饰器
1 ''' 2 5、有参装饰器 3 ''' 4 # login_user={'user':None,'status':False} 5 # 在包一个函数,根据作用域特性传值 6 # def auth(db_tpye): 7 # def auth2(func): 8 # def wrapper(*args,**kwargs): 9 # #传进来了 10 # if db_tpye == 'file': 11 # if login_user['user'] and login_user['status']: 12 # res=func(*args,**kwargs) 13 # return res 14 # else: 15 # name=input('name: ') 16 # password=input('pwd: ') 17 # if name == 'shuyang' and password == '123': 18 # login_user['user']='egon' 19 # login_user['status']=True 20 # print('\033[45mlogin successful\033[0m') 21 # res=func(*args,**kwargs) 22 # return res 23 # else: 24 # print('\033[45mlogin err\033[0m') 25 # elif db_tpye == 'ldap': 26 # print('db_type---->ldap') 27 # return wrapper 28 # return auth2 29 # 30 # @auth('file') 31 # def index(): 32 # print('welcome to index page') 33 # 34 # @auth('ldap') 35 # def home(name): 36 # print('%s welcome to home page' %name) 37 # index() 38 # home('shuyang') 39 ''' 40 结果: 41 name: shuyang 42 pwd: 123 43 login successful 44 welcome to index page 45 db_type---->ldap 46 '''
6、装饰器@functools.wraps
a.官网装饰器定义:
装饰器是一个函数,其主要用途是包装另一个函数或类。这种包装的首要目的是透明地修改或增强被包
装对象的行为。
b.@functools.wraps作用:
因为装饰器是一个闭包函数,怎样能获取被修饰函数的详细信息,如:__name__。
此类实际调用函数的属性。@functools.wraps就提供了该功能。
它是如何实现的,下面的例子是通过反射的原理把func的一些属性更新给了callf函数。原func的属性
不变。但是callf的属性还是跟原func不完全一样,so,如有类似的问题,还需要自己写。
具体,请看未来的类章节。
1 import functools 2 import sys 3 debug_log = sys.stderr 4 5 def trace(func): 6 if debug_log: 7 @functools.wraps(func) 8 def callf(*args, **kwargs): 9 """A wrapper function.""" 10 debug_log.write('Calling function: {}\n'.format(func.__name__)) 11 res = func(*args, **kwargs) 12 debug_log.write('Return value: {}\n'.format(res)) 13 return res 14 return callf 15 else: 16 return func 17 18 @trace 19 def square(x): 20 """Calculate the square of the given number.""" 21 return x * x 22 23 if __name__ == '__main__': 24 print(square(3)) 25 print(square.__doc__) 26 print(square.__name__) 27 ''' 28 结果: 29 Calling function: square 30 Return value: 9 31 9 32 Calculate the square of the given number. 33 square 34 35 不加结果@functools.wraps(func): 36 Calling function: square 37 Return value: 9 38 9 39 A wrapper function. 40 callf 41 '''
三、迭代器
1、迭代的概念:
重复+上一次迭代的结果为下一次迭代的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
a. 不是迭代器
1 # while True: #只满足重复,因而不是迭代 2 # print('====>') 3 4 ''' 5 结果: 6 ====> 7 ====> 8 ====> 9 '''
b. 迭代while写法
1 # 下面才为迭代 2 # list列表是可迭代对象 3 # l = [1, 2, 3] 4 # count = 0 5 # while count < len(l): # 只满足重复,因而不是迭代 6 # print('====>', l[count]) 7 # count += 1 8 ''' 9 结果: 10 ====> 1 11 ====> 2 12 ====> 3 13 ''' 14 15 # tuple元祖是可迭代对象 16 # l = (1, 2, 3) 17 # count = 0 18 # while count < len(l): # 只满足重复,因而不是迭代 19 # print('====>', l[count]) 20 # count += 1 21 ''' 22 结果: 23 ====> 1 24 ====> 2 25 ====> 3 26 ''' 27 28 # 字符串是可迭代对象 29 # s='hello' 30 # count = 0 31 # while count < len(s): 32 # print('====>', s[count]) 33 # count += 1 34 ''' 35 结果: 36 ====> h 37 ====> e 38 ====> l 39 ====> l 40 ====> o 41 '''
ps.总结:while这种方式,指能迭代有序的对象,那无需的想字典、集合、文件如何操作??
2、为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
1 #有序的 2 # [1,2].__iter__() 3 # 'hello'.__iter__() 4 # (1,2).__iter__() 5 #无序的 6 # {'a':1,'b':2}.__iter__() 7 # {1,2,3}.__iter__()
a. 可迭代的对象:内置__iter__方法的,都是可迭代的对象
b. 迭代器:执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法
1 # 列表,可迭代的对象转迭代器使用 2 # i=[1,2,3].__iter__() 3 # 4 # print(i) # 打印一个内存地址 5 ''' 6 结果: 7 <list_iterator object at 0x000000F7C74991D0> 8 ''' 9 # 10 # print(i.__next__()) 11 # print(i.__next__()) 12 # print(i.__next__()) 13 # print(i.__next__()) #抛出异常:StopIteration 14 ''' 15 结果: 16 1 17 Traceback (most recent call last): 18 2 19 File "D:/old_boy/old_boy_17_04/迭代器.py", line 125, in <module> 20 3 21 print(i.__next__()) #抛出异常:StopIteration 22 StopIteration 23 ''' 24 25 # 字典,可迭代的对象转迭代器使用 26 # i={'a':1,'b':2,'c':3}.__iter__() 27 # 28 # print(i.__next__()) 29 # print(i.__next__()) 30 # print(i.__next__()) 31 # print(i.__next__()) #抛出异常:StopIteration 32 ''' 33 结果: 34 Traceback (most recent call last): 35 File "D:/old_boy/old_boy_17_04/迭代器.py", line 142, in <module> 36 print(i.__next__()) 37 StopIteration 38 a 39 b 40 c 41 ''' 42 43 # 字典,可迭代的对象转迭代器使用之异常处理 44 # dic={'a':1,'b':2,'c':3} 45 # i=dic.__iter__() 46 # while True: 47 # try: 48 # key=i.__next__() 49 # print(dic[key]) 50 # except StopIteration: 51 # break 52 ''' 53 结果: 54 1 55 2 56 3 57 ''' 58 59 # 集合,可迭代的对象转迭代器使用 60 # __iter__ == iter() 61 # s={'a',3,2,4} 62 # s.__iter__() #iter(s) 63 # i=iter(s) 64 # print(next(i)) 65 # print(next(i)) 66 # print(next(i)) 67 # print(next(i)) 68 # print(next(i)) 69 ''' 70 结果: 71 Traceback (most recent call last): 72 2 73 File "D:/old_boy/old_boy_17_04/迭代器.py", line 180, in <module> 74 print(next(i)) 75 3 76 StopIteration 77 4 78 a 79 ''' 80 81 # ps.字符串,内置函数 82 # s='hello' 83 # print(s.__len__()) 84 # 85 # print(len(s)) 86 # 总结: 87 # len(s)====== s.__len__()
3、如何判断一个对象是可迭代的对象,还是迭代器对象?
a. 讨论数据对象
1 # 'abc'.__iter__() # 字符串str 2 # ().__iter__() # 元祖tuple 3 # [].__iter__() # 列表list 4 # {'a':1}.__iter__() # 字典dict 5 # {1,2}.__iter__() # 集合set 6 # f = open('a.txt','w') # 文件file 7 # f.__iter__()
b. 可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象。及可迭代对象通过__iter__转成迭代器对象
1 ''' 2 b. 可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象。及可迭代对象通过__iter__转成迭代器对象 3 ''' 4 # 下列数据类型都是可迭代的对象 5 # from collections import Iterable,Iterator 6 # print(isinstance('abc',Iterable)) 7 # print(isinstance([],Iterable)) 8 # print(isinstance((),Iterable)) 9 # print(isinstance({'a':1},Iterable)) 10 # print(isinstance({1,2},Iterable)) 11 # f = open('a.txt','w') 12 # print(isinstance(f,Iterable)) 13 ''' 14 结果: 15 True 16 True 17 True 18 True 19 True 20 True 21 '''
c. 迭代器对象:对象有__next__,对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
1 ''' 2 c. 迭代器对象:对象有__next__,对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身 3 ''' 4 # 只有文件是迭代器对象 5 # from collections import Iterable,Iterator 6 # print(isinstance('abc',Iterator)) 7 # print(isinstance([],Iterator)) 8 # print(isinstance((),Iterator)) 9 # print(isinstance({'a':1},Iterator)) 10 # print(isinstance({1,2},Iterator)) 11 # f = open('a.txt','w') 12 # print(isinstance(f,Iterator)) 13 ''' 14 结果: 15 False 16 False 17 False 18 False 19 False 20 True 21 '''
4、可迭代对象通过__iter__转成迭代器对象
a.迭代协议:
对象有__next__
对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
1 # 对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身 2 # f = open('a.txt','r') 3 # f1=f.__iter__() 4 # 5 # print(f) 6 # print(f1) 7 # print(f is f1) 8 ''' 9 结果: 10 <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'> 11 <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'> 12 True 13 ''' 14 15 # 可迭代对象list,可以看出就是一个迭代器 16 # l=[] 17 # i=l.__iter__() 18 # 19 # print(i.__iter__()) 20 # print(i) 21 # print(l) 22 ''' 23 结果: 24 <list_iterator object at 0x00000038DA2B9320> 25 <list_iterator object at 0x00000038DA2B9320> 26 [] 27 ''' 28 29 # dict字典,以前的调用方式 30 # dic={'name':'egon','age':18,'height':'180'} 31 # print(dic.items()) 32 # 33 # for k,v in dic.items(): 34 # print(k,v) 35 ''' 36 结果: 37 dict_items([('name', 'egon'), ('age', 18), ('height', '180')]) 38 name egon 39 age 18 40 height 180 41 ''' 42 43 # dict字典,while迭代器调用 44 # dic={'name':'egon','age':18,'height':'180'} 45 # i=iter(dic) 46 # while True: 47 # try: 48 # k=next(i) 49 # print(k) 50 # except StopIteration: 51 # break 52 ''' 53 结果: 54 name egon 55 age 18 56 height 180 57 ''' 58 59 # for迭代调用 60 # dic={'name':'egon','age':18,'height':'180'} 61 # for k in dic: #i=iter(dic) k=next(i) 62 # print(k) 63 # print(dic[k]) 64 ''' 65 结果: 66 name 67 egon 68 age 69 18 70 height 71 180 72 ''' 73 74 # list的for循环迭代 75 # l=['a','b',3,9,10] 76 # for i in l: 77 # print(i) 78 ''' 79 结果: 80 a 81 b 82 3 83 9 84 10 85 ''' 86 87 # 文件迭代器,直接可以for循环迭代 88 # with open('a.txt','r',encoding='utf-8') as f: 89 # for line in f: 90 # print(line.strip()) 91 ''' 92 结果: 93 1111 94 2222 95 3333 96 4444 97 5555 98 6666 99 7777 100 '''
ps.
总结:
python中for就是通过迭代的方式来实现调用的。while只是普通的循环
for迭代 == while + try...except...(异常处理方式)
5、 迭代器的优点和缺点
a.优点:
1. 提供了一种不依赖下标的迭代方式
1 # 提供了一种不依赖下标的迭代方式 2 # l=[10000,2,3,4,5] 3 # i=iter(l) 4 # print(i) 5 # print(next(i)) 6 ''' 7 结果: 8 <list_iterator object at 0x000000696CAF91D0> 9 10000 10 '''
2. 就迭代器本身来说,更节省内存。迭代一个值,原来迭代的值丢弃
b.缺点:
1. 无法获取迭代器对象的长度
2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退
1 # 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退 2 # f=open('a.txt',encoding='utf-8') 3 # 4 # for line in f.readlines(): 5 # print(line.strip()) 6 # 7 # print(next(f)) 8 ''' 9 Traceback (most recent call last): 10 1111 11 File "D:/old_boy/old_boy_17_04/迭代器.py", line 398, in <module> 12 2222 13 3333 14 4444 15 5555 16 6666 17 7777 18 print(next(f)) 19 StopIteration 20 ''' 21 22 # f=open('a.txt',encoding='utf-8') 23 # print(next(f)) 24 # for line in f: 25 # print(line.strip()) 26 ''' 27 结果: 28 1111 29 30 2222 31 3333 32 4444 33 5555 34 6666 35 7777 36 ''' 37 38 39 # 列表迭代 40 # l=[10000,2,3,4,5] 41 # 42 # i=iter(l) 43 # 44 # for item in i: 45 # print(item) 46 # print('=============================') 47 # for item in i: 48 # print(item) 49 ''' 50 结果: 51 10000 52 2 53 3 54 4 55 5 56 ============================= 57 '''
ps. 枚举函数enumerate(),实际也是迭代器
l=[10000,2,3,4,5]
i=enumerate(l)
print(next(i))
print(next(i))
四、函数之生成器
生成器: 只要函数体包含yield关键字,该函数就是生成器函数。
return函数
1 ''' 2 return 3 ''' 4 # def foo(): 5 # return 1 6 # return 2 7 # return 3 8 # return 4 9 # 10 # res1=foo() 11 # print(res1) 12 # 13 # res2=foo() 14 # print(res2) 15 ''' 16 结果: 17 1 18 1 19 '''
1、生成器就是迭代器
1 ''' 2 1、生成器就是迭代器 3 ''' 4 # def foo(): 5 # print('first') 6 # yield 1 7 # print('second') 8 # yield 2 9 # print('third') 10 # yield 3 11 # print('fourth') 12 # yield 4 13 # print('fifth') 14 # 15 # g=foo() 16 # for i in g: 17 # print(i) 18 ''' 19 结果: 20 first 21 1 22 second 23 2 24 third 25 3 26 fourth 27 4 28 fifth 29 ''' 30 # print(g) 31 # 32 # print(next(g)) #触发迭代器g的执行,进而触发函数的执行 33 # print(next(g)) 34 # print(next(g)) 35 # print(next(g)) 36 # print(next(g)) 37 ''' 38 结果2 39 <generator object foo at 0x00000023D6DBB200> 40 first 41 1 42 second 43 2 44 third 45 3 46 fourth 47 4 48 fifth 49 Traceback (most recent call last): 50 File "D:/old_boy/old_boy_17_04/生成器.py", line 54, in <module> 51 print(next(g)) 52 StopIteration 53 '''
2、生成器简单调用
1 ''' 2 2、生成器简单调用 3 ''' 4 # def counter(n): 5 # print('start...') 6 # i=0 7 # while i < n: 8 # yield i 9 # i+=1 10 # print('end...') 11 # 12 # 13 # g=counter(5) 14 # print(g) 15 # print(next(g)) 16 # print(next(g)) 17 # print(next(g)) 18 # print(next(g)) 19 # print(next(g)) 20 # print(next(g)) 21 ''' 22 结果: 23 Traceback (most recent call last): 24 <generator object counter at 0x000000089E27B200> 25 File "D:/old_boy/old_boy_17_04/生成器.py", line 109, in <module> 26 start... 27 print(next(g)) 28 0 29 StopIteration 30 1 31 2 32 3 33 4 34 end... 35 '''
3、总结:yield的功能
a. 相当于为函数封装好__iter__和__next__
b. return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
4、yield程序实例(tail -f a.txt | grep 'python' 类功能python程序版)
1 #tail -f a.txt | grep 'python' 类功能python程序版 2 3 # import time 4 # def tail(filepath): 5 # ''' 6 # tail功能 7 # :param filepath: 文件路径 8 # :return: 相当于return文件最后一行,后等待文件输入 9 # ''' 10 # with open(filepath,encoding='utf-8') as f: 11 # ''' 12 # seek(offset,whence=0) 13 # offset:开始的偏移量,也就是代表需要移动偏移的字节数 14 # whence:给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起, 15 # 1代表从当前位置开始算起,2代表从文件末尾算起。默认为0 16 # ''' 17 # f.seek(0,2) 18 # while True: 19 # line=f.readline().strip() 20 # if line: 21 # yield line 22 # else: 23 # time.sleep(0.2) 24 # 25 # #相当于return文件最后一行,后继续等待next下次调用 26 # t=tail('a.txt') 27 # 28 # # 测试tail功能是否有效 29 # # for line in t: 30 # # print(line) 31 # 32 # def grep(pattern,lines): 33 # ''' 34 # grep 功能实现 35 # :param pattern: 校验关键字 36 # :param lines: 要校验的行 37 # :return: 相当于return符合检验的行,后等待行继续调用输入 38 # ''' 39 # for line in lines: 40 # if pattern in line: 41 # yield line 42 # 43 # 44 # g=grep('python',tail('a.txt')) 45 # #返回内存地址 46 # print(g) 47 # 48 # #迭代输出 49 # for i in g: 50 # print(i)
五、内置函数
1、数学运算
abs(), round(),pow(),divmod(),max(),min(),sum()
1 ''' 2 1、数学运算 3 ''' 4 # abs(-5) # 取绝对值,也就是5 5 # round(2.623423, 4) # 四舍五入取整,也就是3.0, 4为精准到四位四舍五入 6 # pow(2, 3) # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5 7 # divmod(9, 2) # 返回除法结果和余数 8 # max([1, 5, 2, 9]) # 求最大值 9 # min([9, 2, -4, 2]) # 求最小值 10 # sum([2, -1, 9, 12]) # 求和
2、工厂函数
int(), float(), str(), bool(), slice(), list(), tuple(), dict(), set(), frozenset()
1 # int("5") # 转换为整数 integer 2 # float(2) # 转换为浮点数 float 3 # str(2.3) # 转换为字符串 string 4 # bool(0) # 转换为相应的真假值,在Python中,0相当于False在Python中,下列对象都相当于False:[], (), {}, 0, None, 0.0, '' 5 # slice(5, 2, -1) # 构建下标对象 slice,切片函数 6 # list((1, 2, 3)) # 转换为表 list 7 # tuple([2, 3, 4]) # 转换为定值表 tuple 8 # dict(a=1, b="hello", c=[1, 2, 3]) # 构建词典 dictionary 9 # set() 创建集合函数 10 # frozenset() 创建一个不可修改的集合 如:s=frozenset({1,2}) # 定义不可变集合
3、类型转换
ord(), chr(), bin(), hex(), oct(), complex()
1 # ord("A") # "A"字符对应的数值 2 # chr(65) # 数值65对应的字符 3 # bin(56) # 返回一个字符串,表示56的二进制数 4 # hex(56) # 返回一个字符串,表示56的十六进制数 5 # oct(56) # 返回一个字符串,表示56的八进制数 6 # complex(3, 9) # 返回复数 3 + 9j
4、序列操作
all(), any(), sorted(), reversed()
1 # all([True, 1, "hello!"]) # 是否所有的元素都相当于True值 2 # any(["", 0, False, [], None]) # 是否有任意一个元素相当于True值 3 # sorted([1,5,3]) # 返回正序的序列,也就是[1,3,5] 4 # reversed([1,5,3]) # 返回反序的序列,也就是[3,5,1]
5、编译执行函数
repr(), compile(), eval(), exec()
1 # repr(me) # 返回一个对象的字符串表示。有时可以使用这个函数来访问操作。 2 # compile("print('Hello')",'test.py','exec') # 编译字符串成为code对象 3 # eval("1 + 1") # 解释字符串表达式。参数也可以是compile()返回的code对象 4 ''' 5 # cmd='print("你瞅啥")' 6 # 7 # dic="{'a':1,'b':2}" 8 # d=eval(dic) 9 # print(type(d),d['a']) 10 # 11 # with open('user.db','w',encoding='utf-8') as f: 12 # user_dic={'name':'egon','password':'123'} 13 # f.write(str(user_dic)) 14 # 15 # with open('user.db','r',encoding='utf-8') as f: 16 # dic=f.read() 17 # print(dic,type(dic)) 18 # dic=eval(dic) 19 # print(dic['name']) 20 ''' 21 # exec("print('Hello')") # exec()执行字符串或complie方法编译过的字符串,没有返回值
6、帮助函数
dir(), help(), id(), len(), challables()
1 ''' 2 6、帮助函数 3 ''' 4 # dir() 不带参数时返回当前范围内的变量,方法和定义的类型列表,带参数时返回参数的属性,方法列表 5 ''' 6 l=[] 7 print(dir(l)) #查看一个对象下面的属性 8 ''' 9 # help() 返回对象的帮助文档 10 ''' 11 print(help(l)) 12 ''' 13 # id() 返回对象的内存地址 14 ''' 15 # x=1 16 # y=x 17 # print(id(x),id(y)) 18 # 19 # print(x is y) #判断的是身份 20 ''' 21 # len() 返回对象长度,参数可以是序列类型(字符串,元组或列表)或映射类型(如字典) 22 # challable() 判断对象是否可以被调用,能被调用的对象就是一个callables对象,比如函数和带有__call__()的实例 23 ''' 24 def func(): 25 pass 26 print(callable(func)) 27 '''
7、作用域查看函数
globals(), locals(), vars()
1 # globals() 返回一个描述当前全局变量的字典 2 # locals() 打印当前可用的局部变量的字典 3 # vars() # 1. 当函数不接收参数时,其功能和locals函数一样,返回当前作用域内的局部变量。 4 # 2. 当函数接收一个参数时,参数可以是模块、类、类实例,或者定义了__dict__属性的对象。
8、迭代器函数
iter(), next(), enumerate(), range()#python3中为生成一个迭代器
1 ''' 2 8、迭代器函数 3 ''' 4 ''' 5 iter(o[, sentinel]) 6 返回一个iterator对象。该函数对于第一个参数的解析依赖于第二个参数。 7 如果没有提供第二个参数,参数o必须是一个集合对象,支持遍历功能(__iter__()方法)或支持序列功能(__getitem__()方法), 8 参数为整数,从零开始。如果不支持这两种功能,将处罚TypeError异常。 9 如果提供了第二个参数,参数o必须是一个可调用对象。在这种情况下创建一个iterator对象,每次调用iterator的next()方法来无 10 参数的调用o,如果返回值等于参数sentinel,触发StopIteration异常,否则将返回该值。 11 ''' 12 # next() 返回一个可迭代数据结构(如列表)中的下一项 13 # enumerate() # 返回一个可以枚举的对象,该对象的next()方法将返回一个元组 14 # x=range(10) 15 # enumerate([1,2,3]).__next__() 16 # range() 根据需要生成一个指定范围的数字,可以提供你需要的控制来迭代指定的次数
9、其他函数
hash(), filter(), format(), input(), open(), print(), zip(), map(), __import__
1 # hash() 哈希值用于快递比价字典的键。 2 # 1. 只要校验的内容一致,那hash得到结果永远一样 3 # 2. 不可逆 4 # 3. 只要采用的哈希算法一样,那无论被校验的内容有多长,hash的到的结果长度都一样 5 # print(hash('asdfasdfsadf')) 6 # print(hash('asdfasdfsadf')) 7 8 # filter() 过滤器,构造一个序列,等价于[ item for item in iterables if function(item)],在函数中设定过滤条件,逐一循环迭代器中的元素,将返回值为True时的元素留下,形成一个filter类型数据 9 ''' 10 filter(function, iterable) 11 参数function:返回值为True或False的函数,可以为None。 12 参数iterable:序列或可迭代对象。 13 >>> def bigerthan5(x): 14 ... return x > 5 15 >>> filter(bigerthan5, [3, 4, 5, 6, 7, 8]) 16 [6, 7, 8] 17 ''' 18 19 # format() #格式化输出字符串,format(value, format_spec)实质上是调用了value的__format__(format_spec)方法 20 ''' 21 "I am {0}, I like {1}!".format("wang", "moon") 22 "I am {}, I like {}!".format("wang", "moon") 23 "I am {name}, I like {msg}!".format(name = "wang", msg ="moon") 24 ''' 25 26 # input() #获取用户输入内容 27 # open() 打开文件 28 # print() 输出函数 29 30 # zip() 拉链函数将对象逐一配对 31 # s='helloo' 32 # l=[1,2,3,4,5] 33 # 34 # z=zip(s,l) 35 # print(z) 36 # for i in z: 37 # print(i) 38 39 40 # import time 41 # m=__import__('time') #以字符串的形式导入模块 42 # m.sleep(3000) 43 44 ''' 45 map(function, iterable,...) 46 对于参数iterable中的每个元素都应用fuction函数,并将结果作为列表返回。 47 如果有多个iterable参数,那么fuction函数必须接收多个参数,这些iterable中相同索引处的元素将并行的作为function函数的参数。 48 如果一个iterable中元素的个数比其他少,那么将用None来扩展改iterable使元素个数一致。 49 如果有多个iterable且function为None,map()将返回由元组组成的列表,每个元组包含所有iterable中对应索引处值。 50 参数iterable必须是一个序列或任何可遍历对象,函数返回的往往是一个列表(list)。 51 52 li = [1,2,3] 53 data = map(lambda x :x*100,li) 54 print(type(data)) 55 data = list(data) 56 print(data) 57 58 运行结果: 59 60 <class 'map'> 61 [100, 200, 300] 62 '''
10、面向对象使用函数
super(), isinstance(), issubclass(), classmethod(), staticmethod(), proerty(), delatter(), hasattr(), getattr(), setattr()
1 #super() 调用父类的方法 2 3 # isinstance() 检查对象是否是类的对象,返回True或False 4 # issubclass() 检查一个类是否是另一个类的子类。返回True或False 5 6 7 # classmethod() # 用来指定一个方法为类的方法,由类直接调用执行,只有一个cls参数,执行雷的方法时,自动将调用该方法的类赋值给cls.没有此参数指定的类的方法为实例方法 8 # staticmethod 9 # property 10 11 # delattr() # 删除对象的属性 12 # hasattr 13 ''' 14 hasattr(object,name) 15 判断对象object是否包含名为name的特性(hasattr是通过调用getattr(object,name))是否抛出异常来实现的。 16 参数object:对象 17 参数name:特性名称 18 >>> hasattr(list, 'append') 19 True 20 >>> hasattr(list, 'add') 21 False 22 ''' 23 #getattr() 获取对象的属性 24 #setattr() 与getattr()相对应