1_线程
00_线程的总结
"""
重点搞清楚什么是多任务,怎样完成多任务
多任务:
在一个程序里边,有多个while True,多个函数,多个部分功能不同的代码,想要让他们一起执行,
或者按照一定顺序(规律)执行就是多任务
线程:
实现多任务的一种基本的方式,比较轻量级,简洁(杀鸡用鸡刀,不用牛刀)
import threading
t1 = threading.Thread(target=test1,args=(,))
t2 = threading.Thread(target=test2,元组参数)
t1.start()
t2.start()
多线程共享全局变量:
多线程共享一个全局变量时,若同时出现多个线程对全局变量进行读写,就可能会出现错误
解决的方法规律:1.从逻辑的角度讲来避免(让一个人写,其他人都读)
2.从程序的角度讲来防止这种情况出现(使用互斥锁(上厕所)思想来避免)
互斥锁:(定义全局变量)
mutex.acquire()
....*****.....
mutex.release()
mutex = threading.Lock()
将可能出现问题的代码段锁住,多是出现全局变量的部分
(Python语言中的代码,有时候看上去是一句,实际上真正让操作系统执行时要翻译成很多句),
锁的代码段越少越好,实现了不管哪个方法先被调用,只要有一个调用了会导致另一方调用失败
死锁:
你等我解锁资源,我等你解锁资源,互相等,都不肯先解
解决方法:
1.程序设计是尽量避免(银行家算法:先都不满足,再从少到多逐步满足)
2.添加超时时间
"""
01_没有多任务的代码
import time
def sing ( name) :
for i in range ( 5 ) :
print ( "%s要唱歌..." % name)
time. sleep( 1 )
def dance ( name) :
for i in range ( 5 ) :
print ( "%s要跳舞..." % name)
time. sleep( 1 )
def main ( ) :
name = input ( "请输入要唱歌的人:" )
sing( name)
dance( name)
if __name__ == '__main__' :
main( )
02_多任务_线程_demo
import time
import threading
"""阅读一个程序切忌从上往下一行一行地看,要弄清楚程序先干什么,再干什么
eg:c语言从main()开始看起
"""
"""主线程自上向下运行,当运行到threading.Thread()时,创建一个对象,当这个对象调用start()时
主线程创建一个子线程,子线程开始执行Thread()内部传递给target的函数,则这个函数就可以单独执行
"""
def sing ( ) :
for i in range ( 5 ) :
print ( "%s要唱歌..." )
time. sleep( 1 )
def dance ( ) :
for i in range ( 5 ) :
print ( "%s要跳舞..." )
time. sleep( 1 )
def main ( ) :
t1 = threading. Thread( target= sing)
t2 = threading. Thread( target= dance)
t1. start( )
t2. start( )
if __name__ == '__main__' :
main( )
03_查看线程数
import threading
import time
def dage ( ) :
for i in range ( 5 ) :
print ( "我不做大哥好多年..." )
def dama ( ) :
for i in range ( 5 ) :
print ( "我不做大妈好多年..." )
def main ( ) :
t1 = threading. Thread( target= dage)
t2 = threading. Thread( target= dama)
t1. start( )
time. sleep( 1 )
print ( "调用t1结束..." )
t2. start( )
time. sleep( 1 )
print ( "调用t2结束..." )
print ( threading. enumerate ( ) )
if __name__ == "__main__" :
main( )
04_查看线程数_循环查看当前运行的线程数量
import threading
import time
def dage ( ) :
for i in range ( 5 ) :
print ( "我不做大哥好多年..." )
time. sleep( 1 )
def dama ( ) :
for i in range ( 10 ) :
print ( "我不做大妈好多年..." )
time. sleep( 1 )
def main ( ) :
t1 = threading. Thread( target= dage)
t2 = threading. Thread( target= dama)
t1. start( )
t2. start( )
while True :
print ( threading. enumerate ( ) )
if len ( threading. enumerate ( ) ) == 1 :
break
time. sleep( 1 )
if __name__ == "__main__" :
main( )
05_验证创建线程的时间以及运行时间
import threading
import time
def dage ( ) :
for i in range ( 5 ) :
print ( "我不做大哥好多年..." )
def main ( ) :
print ( threading. enumerate ( ) )
print ( "线程个数:%d" % len ( threading. enumerate ( ) ) )
t1 = threading. Thread( target= dage)
print ( threading. enumerate ( ) )
print ( "线程个数:%d" % len ( threading. enumerate ( ) ) )
t1. start( )
print ( threading. enumerate ( ) )
print ( "线程个数:%d" % len ( threading. enumerate ( ) ) )
if __name__ == "__main__" :
main( )
06_函数里边修改全局变量
num = 100
nums = 200
num2 = [ 11 , 22 ]
"""对于全局变量的修改什么时候需要加global,什么时候不需要的讨论
在一个函数中对全局变量进行修改的时候,到底是否需要global进行说明,要看是否对全局变的
指向进行了修改,如果修改了指向,即让全局变量指向了一个新的地方,则必须使用global
如果仅仅是修改了指向的空间内部的数据,此时不用必须使用global
引用全局变量,不需要golbal声明,修改全局变量,需要使用global声明,特别地,列表、字典等
如果只是修改其中元素的值,可以直接使用全局变量,不需要global声明。
"""
def test1 ( ) :
"""使用global"""
global num
num += 100
def test2 ( ) :
"""不使用global"""
num2. append( 33 )
print ( num)
print ( nums)
print ( num2)
test1( )
test2( )
print ( num)
print ( nums)
print ( num2)
07_线程共享全局变量
import threading
import time
"""线程共享全局变量,子线程和子线程(多线程之间)之间共享全局变量"""
g_num = 100
def test1 ( ) :
global g_num
g_num += 100
print ( "****in test1 g_num = %d " % g_num)
def test2 ( ) :
print ( "****in test2 g_num = %d " % g_num)
def main ( ) :
t1 = threading. Thread( target= test1)
t2 = threading. Thread( target= test2)
t1. start( )
time. sleep( 1 )
t2. start( )
time. sleep( 1 )
print ( "****in main_Thread g_num = %d" % g_num)
if __name__ == '__main__' :
main( )
08_多线程共享全局变量
import threading
import time
"""
线程共享全局变量,子线程和子线程(多线程之间)之间共享全局变量
共享的意义:多任务一般都是配合执行的
"""
g_num = 100
def test1 ( temp) :
"""有实参传递过来的时候,要定义形参"""
temp. append( 33 )
print ( "****in test1 temp = %s " % str ( temp) )
def test2 ( temp) :
print ( "****in test2 temp = %s " % str ( temp) )
g_nums = [ 11 , 22 ]
def main ( ) :
t1 = threading. Thread( target= test1, args= ( g_nums, ) )
t2 = threading. Thread( target= test2, args= ( g_nums, ) )
t1. start( )
time. sleep( 1 )
t2. start( )
time. sleep( 1 )
print ( "****in main_Thread g_nums = %s" % str ( g_nums) )
if __name__ == '__main__' :
main( )
09_线程共享全局变量的问题
import threading
import time
"""线程共享全局变量,子线程和子线程(多线程之间)之间共享全局变量"""
g_num = 0
def test1 ( num) :
global g_num
for i in range ( num) :
g_num += 100
print ( "****in test1 g_num = %d " % g_num)
def test2 ( num) :
global g_num
for i in range ( num) :
g_num += 100
print ( "****in test2 g_num = %d " % g_num)
def main ( ) :
t1 = threading. Thread( target= test1, args= ( 1000000 , ) )
t2 = threading. Thread( target= test2, args= ( 1000000 , ) )
t1. start( )
t2. start( )
time. sleep( 2 )
print ( "****in main_Thread g_num = %d" % g_num)
if __name__ == '__main__' :
main( )
10_使用互斥锁解决资源竞争的问题-1
import threading
import time
"""线程共享全局变量,子线程和子线程(多线程之间)之间共享全局变量"""
g_num = 0
def test1 ( num) :
mutex. acquire( )
global g_num
for i in range ( num) :
g_num += 1
print ( "****in test1 g_num = %d " % g_num)
mutex. release( )
def test2 ( num) :
mutex. acquire( )
global g_num
for i in range ( num) :
g_num += 1
print ( "****in test2 g_num = %d " % g_num)
mutex. release( )
mutex = threading. Lock( )
"""
上互斥锁,在所有可能会出现资源竞争的地方使用互斥锁(mutex.acquire();mutex.release())
将其套起来.使程序同时只有一个线程在做
互斥锁之上厕所思维:
等于多个人抢着去上厕所,第一个抢到的人先进去,上锁,其他人只能在外边等待,
等第一个人上完再抢,以此类推
"""
def main ( ) :
t1 = threading. Thread( target= test1, args= ( 1000000 , ) )
t2 = threading. Thread( target= test2, args= ( 1000000 , ) )
t1. start( )
t2. start( )
time. sleep( 2 )
print ( "****in main_Thread g_num = %d" % g_num)
if __name__ == '__main__' :
main( )
11_使用互斥锁解决资源竞争的问题-2
import threading
import time
"""线程共享全局变量,子线程和子线程(多线程之间)之间共享全局变量"""
g_num = 0
def test1 ( num) :
global g_num
for i in range ( num) :
mutex. acquire( )
g_num += 1
mutex. release( )
print ( "****in test1 g_num = %d " % g_num)
def test2 ( num) :
global g_num
for i in range ( num) :
mutex. acquire( )
g_num += 1
mutex. release( )
print ( "****in test2 g_num = %d " % g_num)
mutex = threading. Lock( )
"""
上互斥锁,在所有可能会出现资源竞争的地方使用互斥锁(mutex.acquire();mutex.release())
将其套起来.使程序同时只有一个线程在做,上锁的原则:被套的代码越少越好
互斥锁之上厕所思维:
等于多个人抢着去上厕所,第一个抢到的人先进去,上锁,其他人只能在外边等待,
等第一个人上完再抢,以此类推
"""
def main ( ) :
t1 = threading. Thread( target= test1, args= ( 1000000 , ) )
t2 = threading. Thread( target= test2, args= ( 1000000 , ) )
t1. start( )
t2. start( )
time. sleep( 2 )
print ( "****in main_Thread g_num = %d" % g_num)
if __name__ == '__main__' :
main( )
12_案例:多任务UDP聊天器
import socket
import threading
def send_masg ( udp_socket, dest_addr) :
"""发送数据 功能独立,单独封装"""
while True :
send_data = input ( "请输入要发送的数据:" )
udp_socket. sendto( send_data. encode( "utf-8" ) , dest_addr)
def recv_masg ( udp_socket) :
"""接受并显示数据"""
while True :
recv_data = udp_socket. recvfrom( 1024 )
print ( "接收到的数据是:%s" % str ( recv_data[ 0 ] . decode( "utf-8" ) ) )
def main ( ) :
udp_socket = socket. socket( socket. AF_INET, socket. SOCK_DGRAM)
udp_socket. bind( ( "" , 7890 ) )
dest_ip = input ( "请输入要发送目标的ip:" )
dest_port = int ( input ( "请输入要发送目标的port:" ) )
dest_addr = ( dest_ip, dest_port)
t_send_masg = threading. Thread( target= send_masg, args= ( udp_socket, dest_addr) )
t_recv_masg = threading. Thread( target= recv_masg, args= ( udp_socket, ) )
t_send_masg. start( )
t_recv_masg. start( )
if __name__ == '__main__' :
main( )
2_进程
00_进程总结
"""
1.进程:一个程序运行起来后,代码+用到的资源称为进程,它是操作系统分配资源的基本单元 进程内部就可以实现多任务,但到底是谁去做呢?
其实进程仅仅是系统进行资源分配和调度的单位,线程拿着进程的资源实现多任务
2.多任务的实现形式有三种:[流水线思想]
形式一--多进程实现多任务:
一个进程内部有一个主线程,从上到下逐步执行,当主线程调用函数或者方法的时候,就在内部
开辟一个新的进程,将原进程中的代码资源都复制过去.形成多个进程同时进行,每个进程内部
仅含有一个主线程
形式二--多线程执行多任务:
一个进程内部有多个线程在执行,一部分完成后再进行下一部分(同时执行)
形式三--多线程多进程实现多任务:
同时有多个进程在执行,每个进程内部有多个线程在执行,每个进程间是彼此独立的
3.多使用多线程,多进程少用,太浪费资源
4.进程的使用:
实现多任务的另一种基本的方式,比较浪费资源
import multiprocessing
p1 = multiprocessing.Process(target=test1,args=(,))
p2 = multiprocessing.Process(target=test2,元组参数)
p1.start()
p2.start()
5.进程之间不共享全局变量
6.多进程之间通过Queue来实现数据共享(在同一个程序内部,同一台电脑上)
创建队列
q = multiprocessing.Queue()
将队列以元组参数的形式传递给子进程
p1 = multiprocessing.Process(target=Download_from_web, args=(q,)
在不同的子进程中对队列进行添加和获取
q.put(i)
data = q.get()
"""
01_多任务_进程_demo
import time
import threading
import multiprocessing
"""阅读一个程序切忌从上往下一行一行地看,要弄清楚程序先干什么,再干什么
eg:c语言从main()开始看起
"""
"""主线程自上向下运行,当运行到threading.Thread()时,创建一个对象,当这个对象调用start()时
主线程创建一个子线程,子线程开始执行Thread()内部传递给target的函数,则这个函数就可以单独执行
"""
def sing ( ) :
for i in range ( 5 ) :
print ( "%s要唱歌..." )
time. sleep( 1 )
def dance ( ) :
for i in range ( 5 ) :
print ( "%s要跳舞..." )
time. sleep( 1 )
def main ( ) :
p1 = multiprocessing. Process( target= sing)
p2 = multiprocessing. Process( target= dance)
p1. start( )
p2. start( )
if __name__ == '__main__' :
main( )
02_获取进程的pid
import time
import multiprocessing
import os
def test ( ) :
while True :
print ( "子进程的pid = %d" % os. getpid( ) )
time. sleep( 2 )
def main ( ) :
print ( "主进程的Pid = %d" % os. getpid( ) )
p = multiprocessing. Process( target= test)
p. start( )
if __name__ == '__main__' :
main( )
03_进程的执行顺序
import time
import multiprocessing
import os
def test ( ) :
while True :
print ( "子进程的 pid = %d" % os. getpid( ) )
time. sleep( 2 )
def test2 ( ) :
while True :
print ( "子进程2 的pid = %d" % os. getpid( ) )
time. sleep( 2 )
def main ( ) :
print ( "主进程的Pid = %d" % os. getpid( ) )
p1 = multiprocessing. Process( target= test)
p2 = multiprocessing. Process( target= test2)
p1. start( )
p2. start( )
if __name__ == '__main__' :
main( )
04_给Process传递参数
import time
import multiprocessing
import os
def test ( a, b, c, * args, ** kwargs) :
print ( "子进程的 pid = %d" % os. getpid( ) )
print ( a)
print ( b)
print ( c)
print ( args)
print ( kwargs)
def main ( ) :
print ( "主进程的Pid = %d" % os. getpid( ) )
p1 = multiprocessing. Process( target= test, args= ( 11 , 22 , 33 , 44 , 55 ) , kwargs= { "mm" : 111 } )
p1. start( )
if __name__ == '__main__' :
main( )
05_多进程之间不共享全局变量
import time
import multiprocessing
import os
def test ( ) :
while True :
nums. append( 44 )
print ( "子进程的pid = %d" % os. getpid( ) )
print ( "在子进程1中 nums = %s" % str ( nums) )
time. sleep( 10 )
def test2 ( ) :
print ( "在子进程2中 nums = %s" % str ( nums) )
nums = [ 11 , 22 , 33 ]
def main ( ) :
print ( "主进程的Pid = %d" % os. getpid( ) )
p1 = multiprocessing. Process( target= test)
p1. start( )
p1. join( )
p2 = multiprocessing. Process( target= test2)
p2. start( )
if __name__ == '__main__' :
main( )
06_多进程之间通过Queue实现数据共享
import multiprocessing
"""
两个进程之间使用队列链接,一个下载数据并往队列里边写数据,一个从队列里读取数据进行处理
只能用于同一个程序内部,同一个电脑上
"""
def Download_from_web ( q) :
"""下载数据"""
data = [ 11 , 22 , 33 , 44 , 55 , 66 ]
for i in data:
q. put( i)
print ( "下载器已经下载完了数据并且存入队列中****" )
def analysis_data ( q) :
"""处理数据"""
waitting_analysis_data = list ( )
while True :
data = q. get( )
waitting_analysis_data. append( data)
if q. empty( ) :
break
print ( waitting_analysis_data)
def main ( ) :
q = multiprocessing. Queue( )
p1 = multiprocessing. Process( target= Download_from_web, args= ( q, ) )
p2 = multiprocessing. Process( target= analysis_data, args= ( q, ) )
p1. start( )
p2. start( )
if __name__ == '__main__' :
main( )
07_创建进程池
from multiprocessing import Pool
import time
import os
import random
def worker ( msg) :
t_start = time. time( )
print ( "%s 开始执行,进程号为:%d" % ( msg, os. getpid( ) ) )
time. sleep( random. random( ) * 2 )
t_stop = time. time( )
print ( msg, "执行完毕,耗时%0.2f" % ( t_stop- t_start) )
def main ( ) :
po = Pool( 3 )
for i in range ( 0 , 10 ) :
po. apply_async( worker, ( i, ) )
print ( "-----start------" )
po. close( )
po. join( )
print ( "------end-------" )
if __name__ == '__main__' :
main( )
08_案例:多任务文件夹copy-v1
"""
文件夹的拷贝:
创建文件夹;
接下来创建的文件只要路径包含文件夹前边的那个文件,那么就在这个文件夹里面
获取要复制的文件夹的名字
接下来把要复制的文件夹的名字,混上将来想要的新文件夹的名字创建一个新的文件夹
接下来把这个文件夹里边的文件名按照文件名打开,把数据读取出来放入另一个文件夹里边去
单个文件的拷贝:
1.用open()打开一个文件
2.再用open()创建一个文件
3.从原文件内部读取数据
4.将读取的数据写入新文件中去
最终思路:
获取要复制的文件夹的名字
创建一个新的文件夹
获取文件夹中所有的待拷贝的文件的名字
创建进程池,由进程池一个一个往进程内输送要拷贝的文件
接下来把这个文件夹里边的文件按照单个文件的拷贝方式,采用多任务的方式写入另一个文件夹中去
单个文件的拷贝:
1.用open()打开一个文件,采用读的方式讲文件中的内容读出来
2.再用open()创建一个文件,采用写的方式将读到的内容写到新建文件中
3.从原文件内部读取数据
4.将读取的数据写入新文件中去
def main():
要实现的效果:输入一个文件夹的名字,接下来程序就开始自己拷贝,拷贝结束后返回:拷贝成功
1.获取用户要copy的文件夹的名字
2.创建一个新的文件夹(接下来要复制原文件夹中的东西到这个新文件夹中来,应该打开原文件夹中的
文件,把里边的数据读出来,用open()新建一个文件在新的文件夹里,接下来把数据读出来写入新的文
件夹就可以了.关键是如何知道原文件夹中的文件名,用ipython3验证知识点)
3.获取文件夹中所有的待拷贝的文件的名字(目的是为了拷贝) 使用listdir()获取
4.创建进程池,将任务放在进程池中的某个进程里边去,接下来这个进程就单独可以复制了
主进程负责向这个进程池中添加任务,进程池中的进程就负责完成文件的拷贝,从而实现了解耦
4.复制原文件夹中的文件,到新的文件夹中的文件去(使用多任务来处理,应如何创建进程,若listdir()
返回了10000个文件名,创建一万个进程去复制,必死无疑,应该借助进程池的重复利用的特性实现
一个进程复制完了一个文件,可以让这个进程再去复制下一个文件)
pass
if __name__ == '__main__':
main()
"""
import os
import multiprocessing
def copy_file ( file_name, old_folder_name, new_folder_name) :
"""完成文件的拷贝"""
print ( "----模拟copy文件:%s 从文件名:%s---到文件名:%s" % ( file_name, old_folder_name, new_folder_name) )
old_f = open ( old_folder_name + "/" + file_name, "rb" )
content = old_f. read( )
old_f. close( )
new_f = open ( new_folder_name + "/" + file_name, "wb" )
new_f. write( content)
new_f. close( )
def main ( ) :
old_folder_name = input ( "请输入要copy的文件夹的名字:" )
try :
new_folder_name = old_folder_name + "复件"
os. mkdir( new_folder_name)
except :
pass
file_names_list = os. listdir( old_folder_name)
print ( file_names_list)
pool = multiprocessing. Pool( 5 )
for file_name in file_names_list:
pool. apply_async( copy_file, args= ( file_name, old_folder_name, new_folder_name) )
pool. close( )
pool. join( )
if __name__ == '__main__' :
main( )
09_案例:多任务文件夹copy-v2
import os
import multiprocessing
"""
添加任务进度:是再添加一个任务来显示进度,还是让主进程来显示?
主进程,反正闲着也是闲着
"""
"""
代码不是一蹴而就的,是经过不断地演变,不断地优化更新形成的,一个版本一个版本做
代码最重要的就是流程,先干什么再干什么
"""
def copy_file ( q, file_name, old_folder_name, new_folder_name) :
"""完成文件的拷贝"""
old_f = open ( old_folder_name + "/" + file_name, "rb" )
content = old_f. read( )
old_f. close( )
new_f = open ( new_folder_name + "/" + file_name, "wb" )
new_f. write( content)
new_f. close( )
q. put( file_name)
def main ( ) :
old_folder_name = input ( "请输入要copy的文件夹的名字:" )
try :
new_folder_name = old_folder_name + "复件"
os. mkdir( new_folder_name)
except :
pass
file_names_list = os. listdir( old_folder_name)
pool = multiprocessing. Pool( 5 )
q = multiprocessing. Manager( ) . Queue( )
for file_name in file_names_list:
pool. apply_async( copy_file, args= ( q, file_name, old_folder_name, new_folder_name) )
pool. close( )
all_file_number = len ( file_names_list)
copy_ok_nums = 0
while True :
"""
显示进度实现思路:
创建队列:multiprocessing.Manager().Queue() # 通过Manage()创建对象来调用Queue()方法
q = multiprocessing.Manager().Queue()
将队列作为一个参数传递到进程池内部,函数接收一下参数(此类参数多在args=内部传递)
pool.apply_async(copy_file, args=(q, file_name, old_folder_name, new_folder_name))
copy_file(q,file_name, old_folder_name, new_folder_name)
如果拷贝完了文件,那么就向队列中写入一个消息,表示已经完成
q.put(file_name) # 子进程调用添加方法知道了拷贝完了谁
q.get() # 主进程调用获取方法
"""
file_name = q. get( )
copy_ok_nums += 1
print ( "\r已完成:%.2f%%" % ( copy_ok_nums* 100 / all_file_number) , end= "" )
if all_file_number == copy_ok_nums:
break
print ( )
if __name__ == '__main__' :
main( )
3_协程
00_协程总结
"""
迭代器,生成器,了解概念即可 能干什么? 怎么实现的?
迭代器:
一大特点:保证了可以使用极少的代码和极小的空间可以生成想要的数据
可以迭代对象说直白一点就是可以用for循环这种方式
如何迭代的:取的是可以迭代的这个对象的里边的某个特殊函数的返回值,这个返回值返回的是一个迭代器
什么叫做迭代器:拥有__iter__()方法和__next__()方法的对象叫做迭代器
核心点:生成器保存的是生成数据的代码,不是生成数据的结果,通过迭代器可以保证,我可以有一些
代码,这些代码是用来生成一个值的,什么时候调用我就什么时候生成减少内存空间,如果要是使用列
表的话,需要先生成所需要数据,存入到列表中,再用for循环遍历取值占用大量的内存空间
生成器:
最大的特点:含有yield,可以让函数的执行先暂停,同时保留暂停时的值,再次调用时继续向下执行
核心点:生成器保存的是生成数据的代码,不是生成数据的结果,可以保证函数只执行一部分反而
返回只要在一个函数中有yield,那么这个函数就不再叫函数而是叫做生成器(模版)
写一个函数名,原来是调用函数,现在变成了创建一个生成器对象
生成器中可以没有__iter__()和__next()__,但依旧是迭代器,故称其为特殊的迭代器
又因为要是迭代器就可以用next()启动,并获取值,所以生成器也可以使用next输出
yield与 return 的区别:使用return后边的值也会返回,但是函数就相当于调用结束了
"""
01_自己实现一个可以迭代的对象-解析版
import time
from collections import Iterable
from collections import Iterator
class Classmate ( object ) :
def __init__ ( self) :
self. names = list ( )
def add ( self, name) :
self. names. append( name)
def __iter__ ( self) :
"""
要想让自己创建出来的实例对象可以使用for in ,
只需要在自己定义的类中添加一个实例方法 __iter__(self)方法即可
"""
return ClassIterator( )
class ClassIterator ( object ) :
"""通过这个类创建出来的对象就可以作为__iter__()方法的返回值了"""
def __iter__ ( self) :
pass
def __next__ ( self) :
return 11
def main ( ) :
"""
想要用for循环的思路:
1.先看看in后边的对象是否可以迭代(基本上创建这个对象的类中使用了__iter__()这个方法就一定可以迭代)
2.这个方法是否返回一个具有__iter__(self)方法和__next__(self)方法的对象的引用
3.调用iter()函数得到对象classmate的__iter__()方法的返回值
(调用iter()函数就会自动调用创建对象classmate的类中的__iter__()方法,同时产生一个返回值)
4.__iter__方法的返回值是一个迭代器
5.只要有了迭代器,for循环就会通过调用迭代器内部的__next__()来取值(通过调用next()函数会自动调用
指定的next()函数内部的对象的这个方法(__next__()方法)),调一次取一个
"""
classmate = Classmate( )
classmate. add( "王五" )
classmate. add( "刘五" )
classmate. add( "孙五" )
for name in classmate:
print ( name)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
02_自己实现一个可以迭代的对象-解析版2
import time
from collections import Iterable
from collections import Iterator
class Classmate ( object ) :
def __init__ ( self) :
self. names = list ( )
def add ( self, name) :
self. names. append( name)
def __iter__ ( self) :
return ClassIterator( self)
class ClassIterator ( object ) :
"""通过这个类创建出来的对象就可以作为__iter__()方法的返回值了"""
def __init__ ( self, obj) :
self. obj = obj
def __iter__ ( self) :
pass
def __next__ ( self) :
return self. obj. names[ 0 ]
def main ( ) :
"""
在真正的开发过程中,往往出现一种场景,我创建了一个对象,对象里边有个列表属性,列表内部放了
我往里边添加的很多东西,那么我能不能用for循环的思路来去用列表里边的值呢?
1.在创建这个对象的类里边必须实现__iter__()方法
2.__iter__方法必须返回一个迭代器的对象
一个类中含有__iter__(self)方法和__next__(self)方法就可以
称为迭代器(可以取对象里边的值)
"""
classmate = Classmate( )
classmate. add( "王五" )
classmate. add( "刘五" )
classmate. add( "孙五" )
for name in classmate:
print ( name)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
03_自己实现一个可以迭代的对象-实际流程完善版
import time
from collections import Iterable
from collections import Iterator
class Classmate ( object ) :
def __init__ ( self) :
self. names = list ( )
def add ( self, name) :
self. names. append( name)
def __iter__ ( self) :
return ClassIterator( self)
class ClassIterator ( object ) :
"""通过这个类创建出来的对象就可以作为__iter__()方法的返回值了"""
def __init__ ( self, obj) :
self. obj = obj
self. i = 0
def __iter__ ( self) :
pass
def __next__ ( self) :
if self. i < len ( self. obj. names) :
ret = self. obj. names[ self. i]
self. i += 1
return ret
else :
raise StopIteration
def main ( ) :
"""
在真正的开发过程中,往往出现一种场景,我创建了一个对象,对象里边有个列表属性,列表内部放了
我往里边添加的很多东西,那么我能不能用for循环的思路来去用列表里边的值呢?
1.在创建这个对象的类里边必须实现__iter__()方法
2.__iter__方法必须返回一个迭代器的对象
一个类中含有__iter__(self)方法和__next__(self)方法就可以
称为迭代器(可以取对象里边的值)
"""
classmate = Classmate( )
classmate. add( "王五" )
classmate. add( "刘五" )
classmate. add( "孙五" )
for name in classmate:
print ( name)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
04_自己实现一个可以迭代的对象-实际流程完善版简化版
import time
from collections import Iterable
from collections import Iterator
class Classmate ( object ) :
def __init__ ( self) :
self. names = list ( )
self. i = 0
def add ( self, name) :
self. names. append( name)
def __iter__ ( self) :
return self
def __next__ ( self) :
if self. i < len ( self. names) :
ret = self. names[ self. i]
self. i += 1
return ret
else :
raise StopIteration
def main ( ) :
classmate = Classmate( )
classmate. add( "王五" )
classmate. add( "刘五" )
classmate. add( "孙五" )
for name in classmate:
print ( name)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
05_fibonacci数列
nums = list ( )
a = 0
b = 1
i = 0
while i < 10 :
nums. append( a)
a, b = b, a+ b
i += 1
for num in nums:
print ( num)
06_fibonacci数列-2迭代器
import time
"""方案二:迭代器方案,全程没有出现列表,即产即传"""
class Fibonacci ( object ) :
def __init__ ( self, all_num) :
self. all_nums = all_num
self. i = 0
self. a = 0
self. b = 1
def __iter__ ( self) :
return self
def __next__ ( self) :
if self. i < self. all_nums:
ret = self. a
self. a, self. b = self. b, self. a+ self. b
self. i += 1
return ret
else :
raise StopIteration
def main ( ) :
fibo = Fibonacci( 10 )
for num in fibo:
print ( num)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
07_自己改fibonacci数列-2迭代器
import time
class Nums ( object ) :
def __init__ ( self) :
self. nums = list ( )
self. i = 0
def add ( self, a) :
self. nums. append( a)
def __iter__ ( self) :
return self
def __next__ ( self) :
if self. i < len ( self. nums) :
ret = self. nums[ self. i]
self. i += 1
return ret
else :
raise StopIteration
def main ( ) :
nums = Nums( )
a = 0
b = 1
t = 0
while t < 10 :
nums. add( a)
a, b = b, a + b
t += 1
for num in nums:
print ( num)
time. sleep( 1 )
if __name__ == "__main__" :
main( )
08_调试技巧-打印信息
def create_fibo ( all_nums) :
"""生成器的第二种创建方式"""
print ( "*****1*****" )
a, b = 0 , 1
i = 0
while i < all_nums:
print ( "*****2*****" )
yield a
print ( "*****3*****" )
a, b = b, a+ b
i += 1
print ( "*****4*****" )
generator_obj = create_fibo( 10 )
ret = next ( generator_obj)
print ( ret)
ret = next ( generator_obj)
print ( ret)
09_生成器研究
def create_fibo ( all_nums) :
"""生成器的第二种创建方式"""
print ( "*****1*****" )
a, b = 0 , 1
i = 0
while i < all_nums:
print ( "*****2*****" )
yield a
print ( "*****3*****" )
a, b = b, a+ b
i += 1
print ( "*****4*****" )
generator_obj = create_fibo( 10 )
generator_obj_2 = create_fibo( 10 )
"""研究一:两个生成器之间的调用顺序没有影响"""
ret = next ( generator_obj)
print ( "generator_obj:" , ret)
ret = next ( generator_obj)
print ( "generator_obj:" , ret)
ret = next ( generator_obj_2)
print ( "generator_obj_2:" , ret)
ret = next ( generator_obj)
print ( "generator_obj:" , ret)
ret = next ( generator_obj)
print ( "generator_obj:" , ret)
ret = next ( generator_obj)
print ( "generator_obj:" , ret)
10_生成器研究2
def create_fibo ( all_nums) :
a, b = 0 , 1
i = 0
while i < all_nums:
yield a
a, b = b, a+ b
i += 1
return "***ok***"
generator_obj_2 = create_fibo( 50 )
"""研究二:异常"""
while True :
try :
ret = next ( generator_obj_2)
print ( "generator_obj_2:" , ret)
except Exception as ret:
print ( ret. value)
break
11_使用生成器完成fibonacci数列
def create_fibo ( all_nums) :
"""生成器的第二种创建方式"""
a, b = 0 , 1
i = 0
while i < all_nums:
yield a
a, b = b, a+ b
i += 1
generator_obj = create_fibo( 10 )
for num in generator_obj:
print ( num)
12_使用send来启动生成器
def create_fibo ( all_nums) :
a, b = 0 , 1
i = 0
while i < all_nums:
ret = yield a
print ( ret)
a, b = b, a+ b
i += 1
generator_obj = create_fibo( 10 )
ret = next ( generator_obj)
print ( ret)
ret = generator_obj. send( "5" )
print ( ret)
13_使用yield完成多任务
import time
"""
并行:有两个任务,但现在我有4个cpu的核一个任务占一个cpu的核同时执行,这就叫做并行(真的多任务,同时完成的)
并发:有很多个任务,但是现在4个cpu的核(发动机,交替进行),这叫并发(假的多任务,短时间内交替完成的同一时刻只有一个在执行
下边程序交替进行,是个假的
协程实现多任务的最大特点:调用一个任务就像调用一个函数一样切换的资源最少,占用空间最小
"""
def tack_1 ( ) :
while True :
print ( "*****1*****" )
time. sleep( 0.1 )
yield
def tack_2 ( ) :
while True :
print ( "*****2*****" )
time. sleep( 0.1 )
yield
def main ( ) :
t1 = tack_1( )
t2 = tack_2( )
while True :
next ( t1)
next ( t2)
if __name__ == "__main__" :
main( )
14_使用greenlet完成多任务
from greenlet import greenlet
import time
"""yield可以实现多任务,greenlet包含它的功能却比它更加简好用"""
def test1 ( ) :
while True :
print ( "---A--" )
gr2. switch( )
time. sleep( 0.5 )
def test2 ( ) :
while True :
print ( "---B--" )
gr1. switch( )
time. sleep( 0.5 )
gr1 = greenlet( test1)
gr2 = greenlet( test2)
gr1. switch( )
15_使用gevent完成多任务
import gevent
import time
"""
greenlet对yield进行了封装,gevent对greenlet进行了再次封装,所以说gevent相当于集合了前两者的全部功能,
在实现多任务的时候最方便实用的就是使用gevent
用多协程实现多任务的一种方式是利用了你原来在等待耗时的这个操作期间,腾出这个时间,去做其他的事情,这就是协程最核心的点
"""
"""
程序运行起来称之为进程,进程是资源分配的单位,线程负责执行代码,一个线程只能做一件事情,多线程可以实现多任务
若只有单线程,通过利用当一个任务在浪费时间的时候,把这个时间利用起来去做其他的事情,实现多任务
协程依赖于线程,线程依赖于进程
"""
def f1 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
gevent. sleep( 1 )
def f2 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
gevent. sleep( 1 )
def f3 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
gevent. sleep( 1 )
print ( "*****1*****" )
g1 = gevent. spawn( f1, 5 )
print ( "*****2*****" )
g2 = gevent. spawn( f2, 5 )
print ( "*****3*****" )
g3 = gevent. spawn( f3, 5 )
print ( "*****4*****" )
g1. join( )
g2. join( )
g3. join( )
17_gevent打补丁
import gevent
import time
from gevent import monkey
monkey. patch_all( )
def f1 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
def f2 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
def f3 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
print ( "*****1*****" )
g1 = gevent. spawn( f1, 5 )
print ( "*****2*****" )
g2 = gevent. spawn( f2, 5 )
print ( "*****3*****" )
g3 = gevent. spawn( f3, 5 )
print ( "*****4*****" )
g1. join( )
g2. join( )
g3. join( )
gevent. joinall( [
gevent. spawn( f1, 5 ) ,
gevent. spawn( f2, 5 ) ,
gevent. spawn( f3, 5 )
] )
18_gevent的最终使用形式
import gevent
import time
from gevent import monkey
monkey. patch_all( )
def f1 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
def f2 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
def f3 ( n) :
for i in range ( n) :
print ( gevent. getcurrent( ) , i)
time. sleep( 0.5 )
gevent. joinall( [
gevent. spawn( f1, 5 ) ,
gevent. spawn( f2, 5 ) ,
gevent. spawn( f3, 5 )
] )
19_爬虫-图片下载器
import urllib. request
import gevent
def downloder ( img_name, img_url) :
req = urllib. request. urlopen( img_url)
img_content = req. read( )
with open ( img_name, "wb" ) as f:
f. write( img_content)
def main ( ) :
gevent. joinall( [
gevent. spawn( downloder, "1.jpg" , 'http://g.hiphotos.baidu.com/image/h%3D300/sign=342e12b86563f624035d3f03b745eb32/203fb80e7bec54e7f0e0839fb7389b504fc26a27.jpg' ) ,
gevent. spawn( downloder, "2.jpg" , 'http://f.hiphotos.baidu.com/image/h%3D300/sign=705ffa145fda81cb51e685cd6267d0a4/4bed2e738bd4b31c5a30865b89d6277f9f2ff8c6.jpg' )
] )
if __name__ == '__main__' :
main( )