Python基础(8)-装饰器、生成器、迭代器
1.装饰器
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数
1)正常函数
#!/usr/local/bin/python3
import time
def is_Prime(num):
if num < 2:
return True
elif num == 2:
return False
else:
for i in (2,num):
if num % i == 0:
return False
return True
def find_Prime():
t1 = time.time()
for i in range(2,10000):
if is_Prime(i):
print(i)
t2 = time.time()
print(t2-t1)
find_Prime()
2)装饰器,无参数,无返回值
#!/usr/local/bin/python3
import time
def display_time(func):
def wrapper():
t1 = time.time()
func()
t2 = time.time()
print(t2-t1)
return wrapper
def is_Prime(num):
if num < 2:
return True
elif num == 2:
return False
else:
for i in (2,num):
if num % i == 0:
return False
return True
@display_time
def find_Prime():
for i in range(2,10000):
if is_Prime(i):
print(i)
find_Prime()
3)装饰器,有返回值
#!/usr/local/bin/python3 import time def display_time(func): def wrapper(): t1 = time.time() result = func() t2 = time.time() print(t2-t1) return result return wrapper def is_Prime(num): if num < 2: return True elif num == 2: return False else: for i in (2,num): if num % i == 0: return False return True @display_time def find_Prime():
count = 0 for i in range(2,10000): if is_Prime(i): count +=1
return count
find_Prime()
4)装饰器,有参数
def display_time(func):
def wrapper(n):
t1 = time.time()
result = func(n)
t2 = time.time()
print(t2-t1)
return result
return wrapper
def is_Prime(num):
if num < 2:
return True
elif num == 2:
return False
else:
for i in (2,num):
if num % i == 0:
return False
return True
@display_time
def find_Prime(n):
count = 0
for i in range(2,n):
if is_Prime(i):
count += 1
return count
find_Prime(10000)
2. 生成器
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。比如我要循环100万次,按py的语法,for i in range(1000000)会先生成100万个值的列表。但是循环到第50次时,我就不想继续了,就退出了。但是90多万的列表元素就白为你提前生成了。
for i in range(1000000):
if i == 50:
break
print(i)
如上,for i in range(1000000)会先生成100万个值的列表。但是循环到第50次时,程序退出了,但是90多万的列表元素已经提前生成了,上述做法,不仅会占用很大的存储空间,而且绝大数元素占用的空间也浪费了。
在Python中,这种一边循环一边计算后面元素的机制,称为生成器:generator。
# 生成器创建
(x * x for x in range(10))
通过next()
函数获得generator的下一个返回值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。通过for循环来迭代它,就不需要关心StopIteration的错误
g = (x * x for x in range(10))
for n in g:
print(n)
3.函数生成器
def fib(max):
a,b = 0,1
n = 0 # 斐波那契数
while n < max:
n = a + b
a = b # 把b的旧值给到a
b = n # 新的b = a + b(旧b的值)
#print(n)
yield n # 程序走到这,就会暂停下来,返回n到函数外面,直到被next方法调用时唤醒
f = fib(100) # 注意这句调用时,函数并不会执行,只有下一次调用next时,函数才会真正执行
print(f)
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
>>>输出结果:
第1个print:
第2个print:1
第3个print:2
第4个print:3
第5个print:5
这就是定义generator的另一种方法。如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator:
generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句暂停并返回数据到函数外,再次被next()调用时
从上次返回的yield语句处继续执行。
4.迭代器
可以直接作用于for
循环的对象统称为可迭代对象:Iterable,可迭代的意思就是可遍历、可循环
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
生成器都是Iterator
对象,但list
、dict
、str
虽然是Iterable
,却不是Iterator
。
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数
为什么list
、dict
、str
等数据类型不是Iterator
?
这是因为Python的Iterator
对象表示的是一个数据流,Iterator对象可以被next()
函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration
错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()
函
数实现按需计算下一个数据,所以Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator
甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。