python distance_to_Python之装饰器、迭代器和生成器

一、基础准备

1.函数嵌套

函数嵌套定义

函数嵌套调用

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #函数的嵌套定义:在一个函数的内部,又定义另外一个函数

2 deff1():3 print('f1')4 deff2():5 print('f2')6 f2()7 f1()8 f2() #会报错,why?->名称空间和作用域有关

View Code

2.名称空间和作用域

什么是名称空间?

存放名字与变量值绑定关系的地方

名称空间的分类

内置名称空间:在python解释器启动时产生,存放一些python内置的名字

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 max=1

2 print(globals())3 print(globals()['__builtins__'])4 print(dir(globals()['__builtins__'])). #dir查看模块的方法

5 '''{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object at>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': '/Users/yanlingzhao/Desktop/python/day4/day4/test.py', '__cached__': None, 'max': 1}6 7 ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']8 '''

View Code

全局名称空间:在执行文件时产生,存放文件级别定义的名字(除了内置名称空间和函数内定义的变量之外的变量)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 x=1

2 deffunc():3 y=2

4 def f1():pass

5 print

6 classFoo:7 deff(self):8 print('test f')9 if x==1:z=3

10 print(globals()) #查看全局名称空间中的存储内容

11 '''{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object at>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'E:/study/code/day4/day4/test.py', '__cached__': None, 'x': 1, 'func': , 'Foo': , 'z': 3}12 '''

View Code

局部名称空间

#局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间

#用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 x=1

2 deffunc():3 y=2

4 def f1():pass

5 print(locals()) #查看局部名称空间内容

6 func()7 '''{'f1': .f1 at 0x00000000026DD9D8>, 'y': 2}8 '''

9

10 classFoo:11 deff(self):12 print(locals())13 '''没有调用函数f,所有不会打印局部名称空间内容'''

View Code

名称空间的加载和查找顺序

#加载顺序:内置---》全局---》局部

#优先掌握一:名字的查找顺序是:局部-》全局-》内置

7237938.html

作用域

#作用域:作用的范围,

#全局作用域:全局存活,全局有效:globals()

#局部作用域:临时存活,局部有效:locals()

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 max=1 #全局作用域,函数内部和文件级别都可以访问

2 deffoo():3 max=2 #局部作用域,只能在函数内部访问

4 print(max)5 foo()6 print(max)7 '''28 1''' #先找全局max=1的名称空间

9 '''''' #注释掉max=1时找到内置变量

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 x=11111111111111111111111111111111111111111111

2 deff1():3 x=1

4 y=2

5 def f2():pass

6 print(locals()) #局部

7 print(globals()) #全局

8

9 f1()10 print(locals() is globals()) #在文件级别全局就等于局部,从本层开始寻找命名空间

11 print(dir(globals()['__builtins__']))

View Code

改变作用域规则的两个关键词global和nonlocal

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #改变作用域规则的两个关键词:global nonlocal

2 x=1

3 deff1():4 global x #使用全局变量

5 x=2

6 print(globals())7 print(locals())8 f1()9 print(x)10 '''{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object at>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': '/Users/yanlingzhao/Desktop/python/day4/day4/test.py', '__cached__': None, 'x': 2, 'f1': }11 {}12 213 '''

14

15

16

17 l=[]18 deff2():19 l.append('f2') #列表是可变类型,所以可以在局部改变全局的值

20

21 f2()22 print(l)23

24

25 #nonlocal可以改变上一层的局部变量

26 x=027 deff1():28 x=1

29 deff2():30 x=2

31 deff3():32 nonlocal x33 x=3

34 print('f3:%s'%x)35 f3()36 print('f2:%s'%x)37 f2()38 print('f3:%s'%x)39 f1()40 '''f3:341 f2:342 f3:1'''

View Code

函数调用时,必须去函数定义的位置去找作用域关系(作用域关系,在函数定义时已经固定了,与函数调用位置无关)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 x=1

2 deff1():3 deff2():4 print(x)5 returnf26

7 func=f1()8 x=10000000

9

10 deffoo(func):11 x=300000000

12 func() #f2()

13 foo(func)14 x=10000000000000000000000

View Code

3.闭包函数

函数对象-》打破函数层级调用关系(函数可以作为参数使用)

作用域->在函数定义时,已经决定了作用域跟调用无关

------》》

闭包函数:1.定义在函数内部的函数

2.包含对外部作用域名字的引用

3.而不是对全局作用域名字的引用

则该内部函数被称作闭包函数

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #闭包函数的应用

2 importrequests3 defindex(url):4 #url = 'www.baidu.com'

5 x=1

6 defwrapper():7 print(x)8 returnrequests.get(url).text9 returnwrapper10 baidu_web=index('http://www.baidu.com') #包裹了百度url的wrapper闭包函数

11 netease_web=index('http://www.163.com') #包裹了网易url的wrapper闭包函数

12 print(baidu_web()) #执行闭包函数

13 print(netease_web())14

15 print(baidu_web.__closure__[0].cell_contents) #输出结果'''http://www.baidu.com'''

16 print(baidu_web.__closure__[1].cell_contents) #输出结果'''1'''

View Code

二、装饰器

1.开放封闭原则:对扩展是开放的,对修改是封闭的

2.什么是装饰器:装饰它人的工具;装饰器本身可以是任意可调用对象,被装饰的对象本身也可以是任意可调用对象

3.装饰器遵循的原则:1)不修改被装饰对象的源代码 2)不修改被装饰对象的调用方式

4.装饰器的目的:在遵循装饰器原则的前提下,为其增加新功能

5.装饰器使用规则:@装饰器名,必须写在装饰器对象的正上方,并且单独一行

代码演示:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #!_*_coding=utf-8_*_

2 importtime3

4 deftimmer(fuc):5 def wrapper(*args,**kwargs):6 start=time.time()7 time.sleep(0.3)8 res=fuc(*args,**kwargs)9 end=time.time()10 print('total time:%s'%(end-start))11 returnres12 returnwrapper13

14 @timmer #index=timmer(index)

15 defindex():16 print('wellcome to index')17 x=1

18 returnx19 @timmer #home=timmer(home)

20 defhome(name):21 print('wellcome to home:%s'%name)22

23 print(index())24 print(home('zyl'))25 '''

26 wellcome to index27 total time:0.30383801460328 129 wellcome to home:zyl30 total time:0.30042600631731 None'''

View Code

6.装饰器分类:无参装饰器和有参装饰器

无参装饰器实例:

账户认证装饰器

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #!_*_coding=utf-8_*_

2

3 '''

4 {'zyl':'123'}5 '''

6 current_user={'user':None}7 defauth(fuc):8 def wrapper(*args,**kwargs):9 if current_user['user']:10 return fuc(*args,**kwargs)11 name = input('name:').strip()12 password = input('password:').strip()13 with open('db.txt', 'r', encoding='utf-8') as f:14 user_dic =eval(f.read())15 if name in user_dic and password ==user_dic[name]:16 res = fuc(*args, **kwargs)17 current_user['user'] =name18 else:19 print('name and pw error')20

21

22

23 returnres24 returnwrapper25

26 @auth27 defindex():28 print('wellcome to my index')29

30 @auth31 defhome(account):32 print('to the account:%s'%account)33

34 index()35 home('text')

View Code

有参装饰器:

1 #!_*_coding=utf-8_*_

2

3 '''

4 {'zyl':'123'}5 '''

6 current_user={'user':None}7 def auth(auth_type='file'):8 defdeco(fuc):9 def wrapper(*args, **kwargs):10 if auth_type == 'file':11 if current_user['user']:12 return fuc(*args, **kwargs)13 name = input('name:').strip()14 password = input('password:').strip()15 with open('db.txt', 'r', encoding='utf-8') as f:16 user_dic =eval(f.read())17 if name in user_dic and password ==user_dic[name]:18 res = fuc(*args, **kwargs)19 current_user['user'] =name20 returnres21 else:22 print('name and pw error')23

24 elif auth_type == 'mysql':25 print('mysql')26 else:27 print('not valid auth_type')28 returnwrapper29 returndeco30

31 @auth('mysql') #@deco

32 defindex():33 print('wellcome to my index')34

35 @auth()36 defhome(account):37 print('to the account:%s'%account)38

39 index()40 home('text')41 '''mysql42 name: zyl43 password: 12344 to the account:text45 '''

继承函数注释内容

from functools import wraps

@wraps(fuc)放到最里面函数定义的上面

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #补充一:wraps

2

3 importtime4 from functools importwraps5

6 deftimmer(func):7 @wraps(func)8 def wrapper(*args,**kwargs):9 start=time.time()10 res=func(*args,**kwargs)11 stop=time.time()12 print('run time is %s' %(stop-start))13 returnres14 returnwrapper15

16

17 @timmer #index=timmer(index)

18 defindex():19 '''这是index函数'''

20 time.sleep(3)21 print('welcome to index')22 return 123

23

24 print(index.__doc__)25 print(help(index))

View Code

多层个继承

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #补充二:一个函数头顶上可以多个装饰器

2 importtime3 from functools importwraps4 current_user={'user':None}5

6 deftimmer(func):7 @wraps(func)8 def wrapper(*args,**kwargs):9 start=time.time()10 res=func(*args,**kwargs)11 stop=time.time()12 print('run time is %s' %(stop-start))13 returnres14 returnwrapper15 def auth(auth_type='file'):16 defdeco(func):17 def wrapper(*args, **kwargs):18 if auth_type == 'file':19 if current_user['user']:20 return func(*args, **kwargs)21 name = input('name:').strip()22 password = input('password:').strip()23

24 with open('db.txt', encoding='utf-8') as f:25 user_dic =eval(f.read())26 if name in user_dic and password ==user_dic[name]:27 res = func(*args, **kwargs)28 current_user['user'] =name29 returnres30 else:31 print('user or password error')32 elif auth_type == 'mysql':33 print('mysql')34

35 elif auth_type == 'ldap':36 print('ldap')37 else:38 print('not valid auth_type')39 returnwrapper40 returndeco41

42

43

44 @timmer #index=timmer(wrapper)

45 @auth() #@deco #index=deco(index) #wrapper

46 defindex():47 '''这是index函数'''

48 time.sleep(3)49 print('welcome to index')50 return 123

51

52 #print(index.__doc__)

53 #print(help(index))

54

55 index()

View Code

三、迭代器

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来

2 #while True: #单纯的重复

3 #print('你瞅啥')

4

5 #l=['a','b','c','d']

6 #count=0

7 #while count < len(l):

8 #print(l[count])

9 #count+=1

10

11 dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不适于没有索引的数据类型

12

13 #迭代器:

14 #可迭代对象iterable:凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象

15 #s='hello'

16 #l=['a','b','c','d']

17 #t=('a','b','c','d')

18 #dic={'name':'egon','sex':'m',"age":18}

19 #set1={1,2,3}

20 #f=open('db.txt')

21

22 #s.__iter__()

23 #l.__iter__()

24 #t.__iter__()

25 #dic.__iter__()

26 #set1.__iter__()

27 #f.__iter__()

28

29

30 #迭代器对象:可迭代对象执行内置的__iter__方法,得到的结果就是迭代器对象

31

32 #dic={'name':'egon','sex':'m',"age":18}

33 #34 #i=dic.__iter__()

35 ## print(i) #iterator迭代器

36 #37 ## i.__next__() #next(i)

38 #print(next(i))

39 #print(next(i))

40 #print(next(i))

41 #print(next(i)) #StopIteration

42 #43 #l=['a','b','c','d']

44 #45 #i=l.__iter__()

46 #print(next(i))

47 #print(next(i))

48 #print(next(i))

49 #print(next(i))

50 #print(next(i)) #StopIteration

51

52

53

54

55 #不依赖于索引的取值方式

56 #l=['a','b','c','d']

57 #dic={'name':'egon','sex':'m',"age":18}

58 #iter_l=iter(l)

59 #iter_dic=iter(dic)

60 #while True:

61 #try:

62 ## print(next(iter_l))

63 #k=next(iter_dic)

64 #print(k,dic[k])

65 #except StopIteration:

66 #break

67

68

69 #什么是迭代器对象:

70 #1 有__iter__,执行得到仍然是迭代本身

71 #2 有__next__

72

73

74 #迭代器对象的优点

75 #1:提供了一种统一的(不依赖于索引的)迭代方式

76 #2:迭代器本身,比起其他数据类型更省内存

77 #l=['a','b','c','d']

78 #i=iter(l)

79

80 #dic={'a':1,'b':2}

81 #x=dic.keys()

82 #print(x)

83 #i=x.__iter__()

84 #85 #with open('a.txt') as f:

86 ## print(next(f))

87 ## print(next(f))

88 ## print(next(f))

89 #f.read()

90

91

92 #迭代器对象的缺点

93 #1:一次性,只能往后走,不能回退,不如索引取值灵活

94 #2:无法预知什么时候取值结束,即无法预知长度

95 #l=['a','b','c','d']

96 #i=iter(l)

97 #print(next(i))

98 #print(next(i))

99 #print(next(i))

100

101

102 #for循环原理

103

104 #105 #l=['a','b','c','d']

106 #for item in l: #iter_l=l.__iter__()

107 #print(item)

108

109

110 #for item in {1,2,3,4}:

111 #print(item)

112

113

114 #with open('a.txt') as f:

115 ## for line in f: #i=f.__iter__()

116 ## print(line)

117 #print(f is f.__iter__())

118

119

120

121

122

123 #补充:判断可迭代对象与迭代器对象(了解)

124

125 from collections importIterable,Iterator126 s='hello'

127 l=['a','b','c','d']128 t=('a','b','c','d')129 dic={'name':'egon','sex':'m',"age":18}130 set1={1,2,3}131 f=open('a.txt')132

133

134 #print(isinstance(s,Iterable))

135 #print(isinstance(l,Iterable))

136 #print(isinstance(t,Iterable))

137 #print(isinstance(dic,Iterable))

138 #print(isinstance(set1,Iterable))

139 #print(isinstance(f,Iterable))

140

141 print(isinstance(s,Iterator))142 print(isinstance(l,Iterator))143 print(isinstance(t,Iterator))144 print(isinstance(dic,Iterator))145 print(isinstance(set1,Iterator))146 print(isinstance(f,Iterator))

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值