- 前言
- 目标读者
- 非目标读者
- 本书的结构
- 以实践为基础
- 硬件
- 杂谈:个人的一点看法
- Python 术语表
- Python 版本表
- 排版约定
- 使用代码示例
- 第一部分 序幕
- 第 1 章 Python 数据模型
- 第二部分 数据结构
- 第 2 章 序列构成的数组
- 第 3 章 字典和集合
- 第 4 章 文本和字节序列
- 第三部分 把函数视作对象
- 第 5 章 一等函数
- 第 6 章 使用一等函数实现设计模式
- 第 7 章 函数装饰器和闭包
- 第四部分 面向对象惯用法
- 第 8 章 对象引用、可变性和垃圾回收
- 第 9 章 符合 Python 风格的对象
- 第 10 章 序列的修改、散列和切片
- 第 11 章 接口:从协议到抽象基类
- 第 12 章 继承的优缺点
- 第 13 章 正确重载运算符
- 第五部分 控制流程
- 第 14 章 可迭代的对象、迭代器和生成器
- 14.1 Sentence 类第1版:单词序列
- 14.2 可迭代的对象与迭代器的对比
- 14.3 Sentence 类第2版:典型的迭代器
- 14.4 Sentence 类第3版:生成器函数
- 14.5 Sentence 类第4版:惰性实现
- 14.6 Sentence 类第5版:生成器表达式
- 14.7 何时使用生成器表达式
- 14.8 另一个示例:等差数列生成器
- 14.9 标准库中的生成器函数
- 14.10 Python 3.3 中新出现的句法:yield from
- 14.11 可迭代的归约函数
- 14.12 深入分析 iter 函数
- 14.13 案例分析:在数据库转换工具中使用生成器
- 14.14 把生成器当成协程
- 14.15 本章小结
- 14.16 延伸阅读
- 第 15 章 上下文管理器和 else 块
- 第 16 章 协程
- 第 17 章 使用期物处理并发
- 第 18 章 使用 asyncio 包处理并发
- 第六部分 元编程
- 第 19 章 动态属性和特性
- 第 20 章 属性描述符
- 第 21 章 类元编程
- 结语
- 延伸阅读
- 附录 A 辅助脚本
- Python 术语表
- 作者简介
- 关于封面
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
A.5 第16章:出租车队离散事件仿真
示例 A-6 是 16.9.2 节讨论的 taxi_sim.py 脚本的完整代码。
示例 A-6 taxi_sim.py:出租车队仿真程序
""" 出租车仿真程序 ============== 在控制台中驱动出租车:: >>> from taxi_sim import taxi_process >>> taxi = taxi_process(ident=13, trips=2, start_time=0) >>> next(taxi) Event(time=0, proc=13, action='leave garage') >>> taxi.send(_.time + 7) Event(time=7, proc=13, action='pick up passenger') >>> taxi.send(_.time + 23) Event(time=30, proc=13, action='drop off passenger') >>> taxi.send(_.time + 5) Event(time=35, proc=13, action='pick up passenger') >>> taxi.send(_.time + 48) Event(time=83, proc=13, action='drop off passenger') >>> taxi.send(_.time + 1) Event(time=84, proc=13, action='going home') >>> taxi.send(_.time + 10) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
运行示例:有两辆出租车,随机种子是10。这是有效的doctest::
>>> main(num_taxis=2, seed=10) taxi: 0 Event(time=0, proc=0, action='leave garage') taxi: 0 Event(time=5, proc=0, action='pick up passenger') taxi: 1 Event(time=5, proc=1, action='leave garage') taxi: 1 Event(time=10, proc=1, action='pick up passenger') taxi: 1 Event(time=15, proc=1, action='drop off passenger') taxi: 0 Event(time=17, proc=0, action='drop off passenger') taxi: 1 Event(time=24, proc=1, action='pick up passenger') taxi: 0 Event(time=26, proc=0, action='pick up passenger') taxi: 0 Event(time=30, proc=0, action='drop off passenger') taxi: 0 Event(time=34, proc=0, action='going home') taxi: 1 Event(time=46, proc=1, action='drop off passenger') taxi: 1 Event(time=48, proc=1, action='pick up passenger') taxi: 1 Event(time=110, proc=1, action='drop off passenger') taxi: 1 Event(time=139, proc=1, action='pick up passenger') taxi: 1 Event(time=140, proc=1, action='drop off passenger') taxi: 1 Event(time=150, proc=1, action='going home') *** end of events ***
模块末尾有个更长的运行示例。
""" import random import collections import queue import argparse import time DEFAULT_NUMBER_OF_TAXIS = 3 DEFAULT_END_TIME = 180 SEARCH_DURATION = 5 TRIP_DURATION = 20 DEPARTURE_INTERVAL = 5 Event = collections.namedtuple('Event', 'time proc action') # BEGIN TAXI_PROCESS def taxi_process(ident, trips, start_time=0): """每次状态变化时向仿真程序产出一个事件""" time = yield Event(start_time, ident, 'leave garage') for i in range(trips): time = yield Event(time, ident, 'pick up passenger') time = yield Event(time, ident, 'drop off passenger') yield Event(time, ident, 'going home') # 结束出租车进程 # END TAXI_PROCESS # BEGIN TAXI_SIMULATOR class Simulator: def __init__(self, procs_map): self.events = queue.PriorityQueue() self.procs = dict(procs_map) def run(self, end_time): """调度并显示事件,直到时间结束""" # 调度各辆出租车的第一个事件 for _, proc in sorted(self.procs.items()): first_event = next(proc) self.events.put(first_event) # 此次仿真的主循环 sim_time = 0 while sim_time < end_time: if self.events.empty(): print('*** end of events ***') break current_event = self.events.get() sim_time, proc_id, previous_action = current_event print('taxi:', proc_id, proc_id * ' ', current_event) active_proc = self.procs[proc_id] next_time = sim_time + compute_duration(previous_action) try: next_event = active_proc.send(next_time) except StopIteration: del self.procs[proc_id] else: self.events.put(next_event) else: msg = '*** end of simulation time: {} events pending ***' print(msg.format(self.events.qsize())) # END TAXI_SIMULATOR def compute_duration(previous_action): """使用指数分布计算操作的耗时""" if previous_action in ['leave garage', 'drop off passenger']: # 新状态是四处徘徊 interval = SEARCH_DURATION elif previous_action == 'pick up passenger': # 新状态是行程开始 interval = TRIP_DURATION elif previous_action == 'going home': interval = 1 else: raise ValueError('Unknown previous_action: %s' % previous_action) return int(random.expovariate(1/interval)) + 1 def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS, seed=None): """初始化随机生成器,构建过程,运行仿真程序""" if seed is not None: random.seed(seed) # 获得可复现的结果 taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL) for i in range(num_taxis)} sim = Simulator(taxis) sim.run(end_time) if __name__ == '__main__': parser = argparse.ArgumentParser( description='Taxi fleet simulator.') parser.add_argument('-e', '--end-time', type=int, default=DEFAULT_END_TIME, help='simulation end time; default = %s' % DEFAULT_END_TIME) parser.add_argument('-t', '--taxis', type=int, default=DEFAULT_NUMBER_OF_TAXIS, help='number of taxis running; default = %s' % DEFAULT_NUMBER_OF_TAXIS) parser.add_argument('-s', '--seed', type=int, default=None, help='random generator seed (for testing)') args = parser.parse_args() main(args.end_time, args.taxis, args.seed) """ 命令行中的运行示例:seed=3,最长用时=120:: # BEGIN TAXI_SAMPLE_RUN $ python3 taxi_sim.py -s 3 -e 120 taxi: 0 Event(time=0, proc=0, action='leave garage') taxi: 0 Event(time=2, proc=0, action='pick up passenger') taxi: 1 Event(time=5, proc=1, action='leave garage') taxi: 1 Event(time=8, proc=1, action='pick up passenger') taxi: 2 Event(time=10, proc=2, action='leave garage') taxi: 2 Event(time=15, proc=2, action='pick up passenger') taxi: 2 Event(time=17, proc=2, action='drop off passenger') taxi: 0 Event(time=18, proc=0, action='drop off passenger') taxi: 2 Event(time=18, proc=2, action='pick up passenger') taxi: 2 Event(time=25, proc=2, action='drop off passenger') taxi: 1 Event(time=27, proc=1, action='drop off passenger') taxi: 2 Event(time=27, proc=2, action='pick up passenger') taxi: 0 Event(time=28, proc=0, action='pick up passenger') taxi: 2 Event(time=40, proc=2, action='drop off passenger') taxi: 2 Event(time=44, proc=2, action='pick up passenger') taxi: 1 Event(time=55, proc=1, action='pick up passenger') taxi: 1 Event(time=59, proc=1, action='drop off passenger') taxi: 0 Event(time=65, proc=0, action='drop off passenger') taxi: 1 Event(time=65, proc=1, action='pick up passenger') taxi: 2 Event(time=65, proc=2, action='drop off passenger') taxi: 2 Event(time=72, proc=2, action='pick up passenger') taxi: 0 Event(time=76, proc=0, action='going home') taxi: 1 Event(time=80, proc=1, action='drop off passenger') taxi: 1 Event(time=88, proc=1, action='pick up passenger') taxi: 2 Event(time=95, proc=2, action='drop off passenger') taxi: 2 Event(time=97, proc=2, action='pick up passenger') taxi: 2 Event(time=98, proc=2, action='drop off passenger') taxi: 1 Event(time=106, proc=1, action='drop off passenger') taxi: 2 Event(time=109, proc=2, action='going home') taxi: 1 Event(time=110, proc=1, action='going home') *** end of events *** # END TAXI_SAMPLE_RUN """
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论