defsimple_coroutine(a):print('-> started: a =',a)b=yieldaprint('-> Received: b =',b)c=yielda+bprint('-> Received: c =',c)c=simple_coroutine(1)print(c.send(None))>>>->started:a=1>>>1print(c.send(2))>>>->Received:b=2>>>3c.send(23333)>>>->Received:c=23333>>>Traceback(mostrecentcalllast):File"/home/lrhaoo/桌面/notebook/fluent_python/tempCodeRunnerFile.md",line17,in<module>c.send(23333)StopIteration
b = yield a这样理解: 启动语句c.send(None)使得程序执行到yield a, 之后一直等待调用者输入,直到执行c.send(2)后,2被赋值给b,之后继续执行到c = yield a + b中的yield a + b,等待下一个输入。(举个例子类比后容易理解:我们写一个a+b的程序,运行后,程序等待我们输入a, 然后等待我们输入b,如果我们输入了a后不输入b,则程序会一直等待)(这样就容易理解激活语句到底使得程序运行到哪里->运行至用户输入)
frominspectimportgetgeneratorstateclassMyException(Exception):passdefdemo_exc_handling():print('-> coroutine started...')whileTrue:try:x=yieldexceptMyException:print('*** MyException handled. Continuing...')else:print('-> coroutine received: {!r}'.format(x))raiseRuntimeError('This line should never run.')cor=demo_exc_handling()cor.send(None)>>>->coroutinestarted...cor.send(2333)>>>->coroutinereceived:2333cor.throw(MyException)>>>***MyExceptionhandled.Continuing...print(getgeneratorstate(cor))>>>GEN_SUSPENDEDcor.close()print(getgeneratorstate(cor))>>>GEN_CLOSED
importrandomfromqueueimportPriorityQueueDEFAULT_NUMBER_OF_TAXIS=3DEFAULT_END_TIME=180SEARCH_DURATION=5TRIP_DURATION=20DEPARTURE_INTERVAL=5classEvent:def__init__(self,time,taxi_id,action):self.time=timeself.taxi_id=taxi_idself.action=actiondef__iter__(self):returniter((self.time,self.taxi_id,self.action))def__lt__(self,rhs):returnself.time<rhs.timedef__repr__(self):return'Event(taxi_id={}, time={}, action={})'.format(self.taxi_id,self.time,self.action)deftaxi_process(taxi_id,trips,start=0):time=yieldEvent(start,taxi_id,'leave garage')foriinrange(trips):time=yieldEvent(time,taxi_id,'pick up passenger')time=yieldEvent(time,taxi_id,'drop off passenger')yieldEvent(time,taxi_id,'going home')defcompute_duration(previous_action):ifprevious_actionin['leave garage','drop off passenger']:interval=SEARCH_DURATIONelifprevious_action=='pick up passenger':interval=TRIP_DURATIONelifprevious_action=='going home':interval=1else:raiseValueError('Unknown previous_action: %s'%previous_action)returnint(random.expovariate(1/interval))+1classSimulator:def__init__(self,taxis):self.events=PriorityQueue()self.taxis=dict(taxis)defrun(self,end):for_,taxi,insorted(self.taxis.items()):first_event=next(taxi)self.events.put(first_event)sim_time=0whilesim_time<end:ifself.events.empty():print('*** end of events ***')breakcurrent_event=self.events.get()sim_time,taxi_id,previous_action=current_eventprint('taxi:',taxi_id,taxi_id*' ',current_event)active_taxi=self.taxis[taxi_id]next_time=sim_time+compute_duration(previous_action)try:next_event=active_taxi.send(next_time)exceptStopIteration:delself.taxis[taxi_id]else:self.events.put(next_event)else:msg='*** end of simulation time: {} events pending ***'print(msg.format(self.events.qsize()))taxis={0:taxi_process(taxi_id=0,trips=2,start=0),1:taxi_process(taxi_id=1,trips=4,start=5),2:taxi_process(taxi_id=2,trips=6,start=10)}sim=Simulator(taxis)sim.run(20)>>>taxi:0Event(taxi_id=0,time=0,action=leavegarage)taxi:0Event(taxi_id=0,time=2,action=pickuppassenger)taxi:1Event(taxi_id=1,time=5,action=leavegarage)taxi:1Event(taxi_id=1,time=8,action=pickuppassenger)taxi:2Event(taxi_id=2,time=10,action=leavegarage)taxi:2Event(taxi_id=2,time=14,action=pickuppassenger)taxi:1Event(taxi_id=1,time=15,action=dropoffpassenger)taxi:1Event(taxi_id=1,time=16,action=pickuppassenger)taxi:2Event(taxi_id=2,time=24,action=dropoffpassenger)***endofsimulationtime:3eventspending***