python函數、裝飾器、迭代器、生成器

目錄:

  • 函數補充進階
    • 函數對象
    • 函數的嵌套
    • 名稱空間與做用域
    • 閉包函數
  • 函數之裝飾器
  • 函數之迭代器
  • 函數之生成器
  • 內置函數

1、函數補充進階

  一、函數對象: python

函數是第一類對象,即函數能夠看成數據傳遞,它的應用形式也被稱爲高階函數,函數的特性以下:算法

a. 能夠被引用sql

 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 '''
View Code

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 '''
View Code

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 '''
View Code

d. 應用app

 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 '''
View Code

 

  二、函數的嵌套ide

閉包函數基礎函數

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 '''
View Code

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 '''
View Code

 

  三、名稱空間與做用域

a. 名稱空間定義(namespace): 名稱與對象之間的關係,能夠將命名空間看作是字典,其中的鍵是名稱,值是對象

 1 '''
 2 一、名稱空間定義(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
View Code

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)
View Code

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屬於局部變量,調用不了
View Code

3.局部名稱空間:調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定

1 # x=10000
2 # def func():
3 # x = 1 局部變量
4 #     x=1
5 #     def f1():
6 #         pass
View Code

 

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 '''
View Code

 

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名稱空間與做用域\n一、名稱空間定義(namespace): 名稱與對象之間的關係,能夠將命名空間看作是字典,其中的鍵是名稱,值是對象\n二、名稱空間的分類: \n    內置名稱空間:隨着python解釋器的啓動而產生\n    全局名稱空間:文件的執行會產生全局名稱空間,指的是文件級別定義的名字都會放入改空間\n    局部名稱空間:調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定\n三、做用域:爲名稱空間的具體應用。他們之間的關係,以下對應:\n    全局做用域:內置名稱空間,全局名層空間\n    局部做用:局部名稱空間\n四、做用於的優先級順序:局部名稱空間---》全局名層空間---》內置名稱空間\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名稱空間與做用域\n一、名稱空間定義(namespace): 名稱與對象之間的關係,能夠將命名空間看作是字典,其中的鍵是名稱,值是對象\n二、名稱空間的分類: \n    內置名稱空間:隨着python解釋器的啓動而產生\n    全局名稱空間:文件的執行會產生全局名稱空間,指的是文件級別定義的名字都會放入改空間\n    局部名稱空間:調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定\n三、做用域:爲名稱空間的具體應用。他們之間的關係,以下對應:\n    全局做用域:內置名稱空間,全局名層空間\n    局部做用:局部名稱空間\n四、做用於的優先級順序:局部名稱空間---》全局名層空間---》內置名稱空間\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名稱空間與做用域\n一、名稱空間定義(namespace): 名稱與對象之間的關係,能夠將命名空間看作是字典,其中的鍵是名稱,值是對象\n二、名稱空間的分類: \n    內置名稱空間:隨着python解釋器的啓動而產生\n    全局名稱空間:文件的執行會產生全局名稱空間,指的是文件級別定義的名字都會放入改空間\n    局部名稱空間:調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定\n三、做用域:爲名稱空間的具體應用。他們之間的關係,以下對應:\n    全局做用域:內置名稱空間,全局名層空間\n    局部做用:局部名稱空間\n四、做用於的優先級順序:局部名稱空間---》全局名層空間---》內置名稱空間\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 '''
View Code

 

  四、閉包函數

函數嵌套的一種方式,必須遵照如下規則:

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 '''
View Code

 

閉包應用:惰性計算

 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 '''
View Code

 

2、函數之裝飾器

裝飾器:修飾別人的工具,修飾添加功能,工具指的是函數
裝飾器自己能夠是任何可調用對象,被裝飾的對象也能夠是任意可調用對象
爲何要用裝飾器?

a. 開放封閉原則:對修改是封閉的,對擴展是開放的
b. 裝飾器就是爲了在不修改被裝飾對象的源代碼以及調用方式的前提下,爲期添加新功能

一、裝飾器的基本寫法

 1 '''
 2 一、裝飾器的基本寫法
 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 '''
View Code

二、多實例添加,及傳參數函數

 1 '''
 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 '''
View Code

三、登陸權限,一次登陸,屢次使用

 1 '''
 2 三、登陸權限,一次登陸,屢次使用
 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 '''
View Code

四、多裝飾器,執行順序

 1 '''
 2 四、多裝飾器,執行順序
 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 '''
View Code

五、有參裝飾器

 1 '''
 2 五、有參裝飾器
 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 '''
View Code

六、裝飾器@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 '''
View Code

 

3、迭代器

一、迭代的概念:

重複+上一次迭代的結果爲下一次迭代的初始值,重複的過程稱爲迭代,每次重複即一次迭代,而且每次迭代的結果是下一次迭代的初始值

a. 不是迭代器

1 # while True: #只知足重複,於是不是迭代
2 #     print('====>')
3 
4 '''
5 結果:
6 ====>
7 ====>
8 ====>
9 '''
View Code

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 '''
View Code

  ps.總結:while這種方式,指能迭代有序的對象,那無需的想字典、集合、文件如何操做??

二、爲何要有迭代器?

對於沒有索引的數據類型,必須提供一種不依賴索引的迭代方式

1 #有序的
2 # [1,2].__iter__()
3 # 'hello'.__iter__()
4 # (1,2).__iter__()
5 #無序的
6 # {'a':1,'b':2}.__iter__()
7 # {1,2,3}.__iter__()
View Code

 

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__()
View Code

 

三、如何判斷一個對象是可迭代的對象,仍是迭代器對象?

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__()
View Code

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 '''
View Code

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 '''
View Code

 

四、可迭代對象經過__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 '''
View Code

 

ps.

總結:
python中for就是經過迭代的方式來實現調用的。while只是普通的循環
for迭代 == while + try...except...(異常處理方式)

五、 迭代器的優勢和缺點

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 '''
View Code

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 '''
View Code

 

ps. 枚舉函數enumerate(),實際也是迭代器

l=[10000,2,3,4,5]
i=enumerate(l)

print(next(i))
print(next(i))

4、函數之生成器

生成器: 只要函數體包含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 '''
View Code

一、生成器就是迭代器

 1 '''
 2 一、生成器就是迭代器
 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 '''
View Code

二、生成器簡單調用

 1 '''
 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 '''
View Code

三、總結:yield的功能

a. 至關於爲函數封裝好__iter__和__next__
b. return只能返回一次值,函數就終止了,而yield能返回屢次值,每次返回都會將函數暫停,下一次next會從上一次暫停的位置繼續執行

四、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)
View Code

 

5、內置函數

  

 

一、數學運算

  abs(), round(),pow(),divmod(),max(),min(),sum()

 1 '''
 2 一、數學運算
 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])  # 求和
View Code

二、工廠函數

  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}) # 定義不可變集合
View Code

三、類型轉換

  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
View Code

四、序列操做

  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]
View Code

五、編譯執行函數

  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方法編譯過的字符串,沒有返回值
View Code

六、幫助函數

  dir(), help(), id(), len(), challables()

 1 '''
 2 六、幫助函數
 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 '''
View Code

七、做用域查看函數

  globals(), locals(), vars()

1 # globals()  返回一個描述當前全局變量的字典
2 # locals()  打印當前可用的局部變量的字典
3 # vars()  # 1. 當函數不接收參數時,其功能和locals函數同樣,返回當前做用域內的局部變量。
4           # 2. 當函數接收一個參數時,參數能夠是模塊、類、類實例,或者定義了__dict__屬性的對象。
View Code

八、迭代器函數

  iter(), next(), enumerate(), range()#python3中爲生成一個迭代器

 1 '''
 2 八、迭代器函數
 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()  根據須要生成一個指定範圍的數字,能夠提供你須要的控制來迭代指定的次數
View Code

九、其餘函數

  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 '''
View Code

十、面向對象使用函數

  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()相對應
View Code
相關文章
相關標籤/搜索