判断XXXX是否是可迭代对象:
from collections import Iterable
isinstance(XXXX, Iterable): 返回是True则可以迭代
__iter__
方法__iter__
方法得到其返回值__iter__
方法的返回值要是一个迭代器__iter__
方法和__next__
方法"""自定义一个迭代器类"""
import time
from collections.abc import Iterable
from collections.abc import Iterator
class Classmate(object):
"""自定义一个存名字的类"""
def __init__(self):
# 定义一个存放名字的列表
self.names = list()
def add(self, name):
# 向列表中添加名字
self.names.append(name)
def __iter__(self):
"""如果想要一个对象成为一个迭代的对象,即可以使用for,那么必须实现__iter__方法, 而且他的返回值的类中必须有__next__方法"""
return ClassIterator(self)
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.current = 0
def __iter__(self):
pass
def __next__(self):
if self.current < len(self.obj.names):
# print(self.obj.names[self.current])
ret = self.obj.names[self.current]
self.current += 1
return ret
else:
# 如果超出则返或异常,则for 将会自动停下来
raise StopIteration
def main():
classmate = Classmate()
classmate.add("张三")
classmate.add("李四")
classmate.add("王五")
print("判断classmate是否是可以迭代的对象:", isinstance(classmate, Iterable))
class_iterator = iter(classmate)
print("判断classmate_iterator是否是迭代器:",isinstance(class_iterator, Iterator))
# print(next(class_iterator))
for name in classmate:
time.sleep(1)
print(name)
if __name__ == "__main__":
main()
__iter__
方法将自己的做为一个迭代器对象进行返回"""自定义一个迭代器类"""
import time
from collections.abc import Iterable
from collections.abc import Iterator
class Classmate(object):
"""自定义一个存名字的类"""
def __init__(self):
# 定义一个存放名字的列表
self.names = list()
self.current = 0
def add(self, name):
# 向列表中添加名字
self.names.append(name)
def __iter__(self):
"""如果想要一个对象成为一个迭代的对象,即可以使用for,那么必须实现__iter__方法, 而且他的返回值的类中必须有__next__方法"""
return self
def __next__(self):
if self.current < len(self.names):
# print(self.obj.names[self.current])
ret = self.names[self.current]
self.current += 1
return ret
else:
# 如果超出则返或异常,则for 将会自动停下来
raise StopIteration
def main():
classmate = Classmate()
classmate.add("张三")
classmate.add("李四")
classmate.add("王五")
print("判断classmate是否是可以迭代的对象:", isinstance(classmate, Iterable))
class_iterator = iter(classmate)
print("判断classmate_iterator是否是迭代器:",isinstance(class_iterator, Iterator))
# print(next(class_iterator))
for name in classmate:
time.sleep(1)
print(name)
if __name__ == "__main__":
main()
利用迭代器,我们可以在每次迭代获取数据(通过next()
方法)时按照特定的规律进行生成,但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们记录,进而才能根据当前状态生成下一个数据,为了达到记录当前状态,并配合next()
函数进行迭代使用,我们可以采用更简便的方法---->生成器.
# 将创建列表的时的[]换成()就可以了
num = (i for i in rnage(10))
# 返回值(num)是一个生成器
"""用yield完成多任务----协程"""
import time
def test1():
while True:
print("----1----")
time.sleep(0.1)
yield
def test2():
while True:
print("----2----")
time.sleep(0.1)
yield
def main():
# 创建一个生成器对象
t1 = test1()
t2 = test2()
# 先让t1运行一会,当t1遇到yield的时候,返回到main的while True中
# 然后执行t2,当t2遇到yield的时候,在切换到t1中
# 这样t1/t2/t1/t2/t1/t2的交替运行,最终实现了多任务 ---- 协程
while True:
next(t1)
next(t2)
if __name__ == "__main__":
main()
"""生成器中的send和next"""
def Create_num(num):
a, b = 0,1
create_nums = 0
while create_nums < num:
# ret 用来接收send发送过来的值
ret = yield a
a, b = b, a+b
print(">>>ret>>>",ret)
create_nums +=1
create_num = Create_num(10)
# ret = create_num.send(None) # 如果非要使用send的话传递的值要为None
# print(ret)
ret = next(create_num)
print(ret)
# 一般send不作为第一个
ret = create_num.send("adnsdj")
print(ret)
为了更好的使用协程来完成多任务,python中greenlet模块对yeid进行了封装,使得切换更简单
from greenlet import greenlet
import time
def test1():
while True:
print("----1----")
# 调用test2
gr2.switch()
time.sleep(0.1)
def test2():
while True:
print("----2----")
# 调用test1
gr1.switch()
time.sleep(0.1)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# 启动第一个函数
gr1.switch()
gevent当程序遇到延时操作的使用自动切换任务
必须使用的是gevent中的sleep,如果程序已经有多中延时操作,可以在开头使用下面的语句将其替换
# 想要用gevent,代码中的延时操作都要用gevent中的 ,如果不这样做的话可以用一下方法:打个补丁:
# 加上以下内容:
from gevent import monkey
monkey.patch_all()
# 加上后那些延时操作都会自动改为gevent版的
举例:
将greenlt版的改为gevent版的
"""使用gevent完成多任务 - 协程"""
import gevent
import time
from gevent import monkey
monkey.patch_all() # 将程序中的延时操作都改成gevent类型
def f1(n):
for i in range(n):
print(gevent.getcurrent(), i) # 打印那个线程执行
time.sleep(1)
def f2(n):
for i in range(n):
print(gevent.getcurrent(), i) # 打印那个线程执行
gevent.sleep(1) # gevent 中的延时 如果没有monkey.patch_all() 必须要将延时操作都改成gevent类型
def main():
"""写法1"""
# print("----1----")
# g1 = gevent.spawn(f1, 5)
# print("----2----")
# g2 = gevent.spawn(f2, 5)
# print("----3----")
# g1.join() # 等待g1运行完
# g2.join() # 等待g2运行完
# 写法2
gevent.joinall([
gevent.spawn(f1, 5),
gevent.spawn(f2, 5)
])
if __name__ == "__main__":
main()
"""普通的斐波那契数列"""
a = 0
b = 1
fibonacci = list()
for i in range(10):
fibonacci.append(a)
a, b = b, a + b
for num in fibonacci:
print(num)
"""斐波那契数列 迭代器版"""
class Fibonacci(object):
def __init__(self, number):
self.number = number # 总数
self.current = 0 # 计数
self.a = 0
self.b = 1
pass
def __iter__(self):
return self
def __next__(self):
if self.current < self.number:
ret = self.a
self.a, self.b = self.b, self.a + self.b
self.current +=1
return ret
else:
# 超出停止
raise StopIteration
fibonacci = Fibonacci(10)
for num in fibonacci:
print(num)
"""普通的斐波那契数列 生成器版"""
def Fibonacci(num_all):
print("----1----")
a, b = 0, 1
current_num = 0
while current_num < num_all:
print("----2----")
yield a # 如果函数中有yeid语句,那么这个就不在是函数, 而是一个生成器的模板
print("----3----")
a, b = b, a+b
current_num += 1
print("----4----")
# 如果在调用 Fibonacci的时候,发现函数中有yield那么此时,不是调用函数,而是创建了一个生成器对象
fibonacci = Fibonacci(10)
x = next(fibonacci)
print(x)
x = next(fibonacci)
print(x)
# for num in fibonacci:
# print(num)
"""并发下载器图片"""
import urllib.request
import gevent
from gevent import monkey
import time
monkey.patch_all() # 替换延时操作
def download(image_file, img_url):
img = urllib.request.urlopen(img_url)
time.sleep(1)
img_f = img.read()
with open(image_file, "wb") as f:
f.write(img_f)
def main():
f1 = "../../static/image/down_img/1.jpg"
f2 = "../../static/image/down_img/2.jpg"
gevent.joinall([
gevent.spawn(download, f1, "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1906469856,4113625838&fm=26&gp=0.jpg" ),
gevent.spawn(download, f2, "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3984473917,238095211&fm=26&gp=0.jpg")
])
print("下载完成")
if __name__ == "__main__":
main()