├── exercise ├── 10 模块 │ └── README.md ├── 11 装饰器 │ ├── README.md │ └── answer │ │ └── README.md ├── 12 多线程 │ ├── README.md │ └── answer │ │ └── README.md ├── 3 变量 │ ├── README.md │ └── answer │ │ └── README.md ├── 4 序列 │ ├── README.md │ └── answer │ │ └── README.md ├── 5 条件和循环 │ ├── README.md │ └── answer │ │ └── README.md ├── 6 映射和集合 │ ├── README.md │ └── answer │ │ └── README.md ├── 7 文件和输入输出 │ ├── README.md │ └── answer │ │ └── README.md ├── 8 错误和异常 │ ├── README.md │ └── answer │ │ └── README.md └── 9 函数 │ ├── README.md │ └── answer │ └── README.md ├── install_python_windows.pdf ├── python_demo ├── 10 │ ├── chinese_zodiac.py │ ├── chinese_zodiac_v2.py │ └── zodiac_v3.py ├── 12 │ └── test_if.py ├── 13 │ └── test_for.py ├── 14 │ └── test_dict.py ├── 19 │ └── file_op.py ├── 21 │ └── exception_handling.py ├── 22 │ └── func_test.py ├── 26 │ ├── name.txt │ ├── sanguo.py │ ├── sanguo.txt │ ├── sanguo_v2.py │ ├── sanguo_v3.py │ └── weapon.txt ├── 28 │ └── func_test2.py ├── 29 │ └── func_test3.py ├── 30 │ └── func_test4.py ├── 31 │ └── func_test5.py ├── 32 │ └── func_test6.py ├── 33 │ ├── mod_test.py │ └── mymod.py ├── 35 │ └── class_test.py ├── 38 │ └── with_test.py ├── 39 │ ├── thread_test.py │ └── thread_testv2.py ├── 40 │ └── con_cus.py ├── 41 │ └── stdlib_test.py ├── 47 │ └── time_test.py ├── 49 │ └── dir_test.py ├── 51 │ └── numpy_test.py ├── 55 │ ├── iris_test.csv │ ├── iris_training.csv │ └── pandas_test.py ├── 59 │ └── plt_test.py ├── 62 │ └── pachong1.py ├── 63 │ └── pachong2.py ├── 64 │ └── pachong3.py ├── 65 │ └── pachong4.py ├── 66 │ └── pachong5.py ├── 69 │ ├── pachong6.py │ └── pachong_infoq.py ├── 70 │ ├── pachong7.py │ └── pachong_infoq2.py ├── 71 │ └── code │ │ ├── Makefile │ │ ├── build │ │ └── lib │ │ │ └── dbdb │ │ │ ├── __init__.py │ │ │ ├── binary_tree.py │ │ │ ├── interface.py │ │ │ ├── logical.py │ │ │ ├── physical.py │ │ │ └── tool.py │ │ ├── dbdb │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── binary_tree.cpython-36.pyc │ │ │ ├── interface.cpython-36.pyc │ │ │ ├── logical.cpython-36.pyc │ │ │ ├── physical.cpython-36.pyc │ │ │ └── tool.cpython-36.pyc │ │ ├── binary_tree.py │ │ ├── interface.py │ │ ├── logical.py │ │ ├── physical.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ ├── __init__.cpython-36.pyc │ │ │ │ ├── test_binary_tree.cpython-36.pyc │ │ │ │ ├── test_integration.cpython-36.pyc │ │ │ │ └── test_physical.cpython-36.pyc │ │ │ ├── test_binary_tree.py │ │ │ ├── test_integration.py │ │ │ └── test_physical.py │ │ └── tool.py │ │ ├── example.db │ │ ├── requirements.txt │ │ ├── setup.py │ │ └── tox.ini ├── .gitignore ├── 04 │ ├── hello_world.py │ └── test1.py ├── 06 │ └── network_bandwidth.py ├── 07 │ └── zodiac.py ├── 08 │ └── zodiac_v2.py └── README.MD ├── python_knowledge_map.jpg ├── setup_pycharm_win10.pdf ├── std_lib.pdf ├── timegeekbang.com ├── .gitignore ├── chinese_zodiac.py ├── chinese_zodiac_v2.py ├── class_test.py ├── code │ ├── Makefile │ ├── build │ │ └── lib │ │ │ └── dbdb │ │ │ ├── __init__.py │ │ │ ├── binary_tree.py │ │ │ ├── interface.py │ │ │ ├── logical.py │ │ │ ├── physical.py │ │ │ └── tool.py │ ├── dbdb │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── binary_tree.cpython-36.pyc │ │ │ ├── interface.cpython-36.pyc │ │ │ ├── logical.cpython-36.pyc │ │ │ ├── physical.cpython-36.pyc │ │ │ └── tool.cpython-36.pyc │ │ ├── binary_tree.py │ │ ├── interface.py │ │ ├── logical.py │ │ ├── physical.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ │ ├── __init__.cpython-36.pyc │ │ │ │ ├── test_binary_tree.cpython-36.pyc │ │ │ │ ├── test_integration.cpython-36.pyc │ │ │ │ └── test_physical.cpython-36.pyc │ │ │ ├── test_binary_tree.py │ │ │ ├── test_integration.py │ │ │ └── test_physical.py │ │ └── tool.py │ ├── example.db │ ├── requirements.txt │ ├── setup.py │ └── tox.ini ├── con_cus.py ├── dir_test.py ├── exception_handling.py ├── file_op.py ├── func_test.py ├── func_test2.py ├── func_test3.py ├── func_test4.py ├── func_test5.py ├── func_test6.py ├── hello_world.py ├── iris_test.csv ├── iris_training.csv ├── mod_test.py ├── mymod.py ├── name.txt ├── network_bandwidth.py ├── numpy_test.py ├── pachong1.py ├── pachong2.py ├── pachong3.py ├── pachong4.py ├── pachong5.py ├── pachong6.py ├── pachong7.py ├── pachong8.py ├── pachong_infoq.py ├── pachong_infoq2.py ├── pandas_test.py ├── plt_test.py ├── sanguo.py ├── sanguo.txt ├── sanguo_v2.py ├── sanguo_v3.py ├── stdlib_test.py ├── test1.py ├── test_dict.py ├── test_for.py ├── test_if.py ├── thread_test.py ├── thread_testv2.py ├── time_test.py ├── weapon.txt ├── with_test.py ├── zodiac.py ├── zodiac_v2.py └── zodiac_v3.py ├── txt ├── Readme.md ├── name.txt ├── sanguo.txt ├── sanguo_utf8.txt └── weapon.txt ├── 在Windows系统上安装Python.pdf └── 零基础学Python.pdf /exercise/10 模块/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 模块 2 | 1. 导入os模块,并使用help(os)查看os模块的帮助文档 3 | 4 | -------------------------------------------------------------------------------- /exercise/11 装饰器/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 定义装饰器,用于打印函数执行的时间 2 | 1. 统计函数开始执行和结束执行的时间 3 | 2. 扩展练习:为装饰器传入超时时间,函数执行超过指定时间后退出 4 | 5 | 6 | 7 | 8 | # 练习二 定义装饰器,实现不同颜色显示执行结果的功能 9 | 1. 向装饰器传递参数,通过传递的参数获取到输出的颜色 10 | 2. 被装饰函数的print( )输出根据装饰器得到的颜色进行输出 11 | -------------------------------------------------------------------------------- /exercise/11 装饰器/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 定义装饰器,用于打印函数执行的时间 2 | 1. 统计函数开始执行和结束执行的时间 3 | 2. 扩展练习:为装饰器传入超时时间,函数执行超过指定时间后退出 4 | ```python 5 | # 为装饰器传入超时时间,函数执行超过指定时间后退出 6 | # windows下signal.SIGALRM不可用 7 | 8 | import time 9 | import signal 10 | 11 | 12 | def timeout(seconds=10, error_message="Timer expired"): 13 | def decorator(func): 14 | def handler(singnum, frame): 15 | raise TimeoutError(error_message) 16 | 17 | def wrapper(*args, **kwargs): 18 | signal.signal(signal.SIGALRM, handler) 19 | signal.alarm(seconds) 20 | try: 21 | result = func(*args, **kwargs) 22 | finally: 23 | signal.alarm(0) 24 | return result 25 | return wrapper 26 | return decorator 27 | 28 | 29 | @timeout(5) 30 | def getinfo(msg): 31 | print("getinfo start!") 32 | print("msg: %s" % msg) 33 | time.sleep(10) 34 | print("getinfo end!") 35 | return 1 36 | 37 | 38 | if __name__ == '__main__': 39 | try: 40 | getinfo('Test!') 41 | except TimeoutError as e: 42 | print("time out: %s" % e) 43 | 44 | ``` 45 | 46 | 47 | # 练习二 定义装饰器,实现不同颜色显示执行结果的功能 48 | ```python 49 | # 1. 向装饰器传递参数,通过传递的参数获取到输出的颜色 50 | # 2. 被装饰函数的print( )输出根据装饰器得到的颜色进行输出 51 | import sys 52 | 53 | 54 | def make_color(code): 55 | def decorator(func): 56 | def color_func(s): 57 | if not sys.stdout.isatty(): 58 | return func(s) 59 | tpl = '\x1b[{}m{}\x1b[0m' 60 | return tpl.format(code, func(s)) 61 | return color_func 62 | return decorator 63 | 64 | 65 | @make_color(33) 66 | def fmta(s): 67 | return '{:^7}'.format(str(float(s) * 1000)[:5] + 'ms') 68 | 69 | ``` -------------------------------------------------------------------------------- /exercise/12 多线程/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 多线程文件名称查找 2 | 1. 对某一文件夹启动10个线程查找文件包含abc三个字符的文件名,并显示该文件所在的路径 3 | 2. 尽量使用面向对象编程方式实现 4 | 5 | 6 | 7 | # 练习二 扩展练习:使用多线程编写一个简单的聊天室 8 | 1. 接收用户的网络连接可以使用socketserver库 9 | 2. 用户首次登陆输入自己的名字和当前在线的用户,支持多人同时登陆 10 | 3. 用户默认发的消息全部人可以收到,用户使用@某一用户可以进行私聊 11 | 12 | 提示: 服务端执行后会监听指定的端口, 客户端可以通过 nc <服务器ip地址> <服务器端口> 方式连接, 如: 13 | 服务端执行 python server.py 后进行监听8000端口, 客户端执行 nc 127.0.0.1 8000 后可以连接到服务端 14 | 客户端A 发送消息给全体人员可以直接输入消息内容, 回车后,其他客户端可见, 客户端A发给客户端B私信可以使用 15 | @客户端B的名字 聊天内容,只有客户端B能够看到聊天内容 16 | -------------------------------------------------------------------------------- /exercise/12 多线程/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 多线程文件名称查找 2 | 1. 对某一文件夹启动10个线程查找文件包含abc三个字符的文件名,并显示该文件所在的路径 3 | 2. 尽量使用面向对象编程方式实现 4 | 5 | 6 | 7 | # 练习二 扩展练习:使用多线程编写一个简单的聊天室 8 | 1. 接收用户的网络连接可以使用socketserver库 9 | 2. 用户首次登陆输入自己的名字和当前在线的用户,支持多人同时登陆 10 | 3. 用户默认发的消息全部人可以收到,用户使用@某一用户可以进行私聊 11 | 12 | 提示: 服务端执行后会监听指定的端口, 客户端可以通过 nc <服务器ip地址> <服务器端口> 方式连接, 如: 13 | 服务端执行 python server.py 后进行监听8000端口, 客户端执行 nc -v 127.0.0.1 8000 后可以连接到服务端 14 | 客户端A 发送消息给全体人员可以直接输入消息内容, 回车后,其他客户端可见, 客户端A发给客户端B私信可以使用 15 | @客户端B的名字 聊天内容,只有客户端B能够看到聊天内容 16 | 17 | ```python 18 | # coding=utf-8 19 | #!/usr/bin/python 20 | 21 | import socketserver 22 | import threading 23 | import socket 24 | import time 25 | import re 26 | 27 | srvip = ('', 8000) 28 | 29 | userg = {} 30 | 31 | timefmt = "%H:%M:%S" 32 | 33 | reg = re.compile(r'^@') 34 | 35 | ## 36 | """ 37 | override socketserver.TcpServer.__init__() 38 | """ 39 | 40 | 41 | class MyTCPServer(socketserver.TCPServer): 42 | socket_lev = socket.SOL_SOCKET 43 | socket_opt = socket.SO_REUSEADDR 44 | 45 | def __init__( 46 | self, 47 | server_address, 48 | RequestHandlerClass, 49 | bind_and_activate=True): 50 | socketserver.BaseServer.__init__( 51 | self, server_address, RequestHandlerClass) 52 | self.socket = socket.socket(self.address_family, 53 | self.socket_type) 54 | self.socket.setsockopt(self.socket_lev, self.socket_opt, 1) 55 | if bind_and_activate: 56 | self.server_bind() 57 | self.server_activate() 58 | 59 | 60 | ## 61 | 62 | class MyThreadingTCPServer(socketserver.ThreadingMixIn, MyTCPServer): 63 | pass 64 | 65 | 66 | class MyTcpHandler(socketserver.StreamRequestHandler): 67 | 68 | def sendtimes(self): 69 | msgsendtime = time.strftime(timefmt, time.localtime()) 70 | return msgsendtime 71 | 72 | def whoonline(self, name): 73 | self.usernames = "" 74 | for key in userg.keys(): 75 | self.usernames = self.usernames + key.strip('\n') + " " 76 | self.sendmsg = "online: %s\n" % self.usernames 77 | self.name = name 78 | userg[self.name].send(self.sendmsg.encode(encoding="utf-8")) 79 | 80 | def newuserlogin(self, name): 81 | self.sendtime = self.sendtimes() 82 | self.name = name 83 | self.sendmsg = "[ %s %s login]\n" % ( 84 | self.sendtime, self.name.strip('\n')) 85 | for key in userg.keys(): 86 | if key == self.name: 87 | continue 88 | else: 89 | userg[key].send(self.sendmsg.encode(encoding="utf-8")) 90 | 91 | def userlogout(self, name): 92 | self.sendtime = self.sendtimes() 93 | self.name = name.strip('\n') 94 | self.sendmsg = "[%s %s logout]\n" % (self.sendtime, self.name) 95 | for key in userg.keys(): 96 | userg[key].send(self.sendmsg.encode(encoding="utf-8")) 97 | 98 | def sendmsgs(self, msg, name): 99 | self.sendtime = self.sendtimes() 100 | self.sendmsg = "[%s %s]: %s" % ( 101 | name.strip('\n'), self.sendtime, msg) 102 | self.name = name 103 | 104 | for key in userg.keys(): 105 | if key == self.name: 106 | continue 107 | else: 108 | userg[key].send(self.sendmsg.encode(encoding="utf-8")) 109 | 110 | def sendmsgtoone(self, msg, name): 111 | self.sendtime = self.sendtimes() 112 | self.toname = msg.split()[0][1:] 113 | msglen = len(msg.split()[0]) + 1 114 | self.tomsg = msg[msglen:] 115 | self.keyname = self.toname + "\n" 116 | if self.keyname not in userg: 117 | self.sendmsg = "ERROE [%s] user not online or not exist\n" % self.toname 118 | userg[name].send(self.sendmsg.encode(encoding="utf-8")) 119 | else: 120 | self.sendmsg = "[%s %s]: %s" % ( 121 | self.name.strip('\n'), self.sendtime, self.tomsg) 122 | userg[self.keyname].send(self.sendmsg.encode(encoding="utf-8")) 123 | 124 | def handle(self): 125 | self.usernames = "" 126 | self.cur_thread = threading.current_thread() 127 | # print "%s Staring..." % self.cur_thread.name 128 | # print threading.active_count() 129 | print('-' * 10, 'Get new connection', '-' * 10) 130 | # print self.request 131 | self.sendmsg = """ 132 | ====================================== 133 | | Welcome to My Server | 134 | | Please Enter You Name: | 135 | | | 136 | ======================================\n""" 137 | self.wfile.write(self.sendmsg.encode(encoding="utf-8")) 138 | self.name = self.rfile.readline().decode() 139 | while not self.name.strip('\n').strip(): 140 | self.wfile.write('Please Enter You Name\n') 141 | self.name = self.rfile.readline().decode() 142 | while True: 143 | if self.name not in userg: 144 | userg[self.name] = self.request 145 | self.sendmsg = "Hello %s" % self.name 146 | self.wfile.write(self.sendmsg.encode(encoding="utf-8")) 147 | self.newuserlogin(self.name) 148 | self.whoonline(self.name) 149 | break 150 | else: 151 | self.wfile.write('Please Enter A New Name:\n') 152 | self.name = self.rfile.readline().decode() 153 | while True: 154 | self.resvmsg = self.rfile.readline().decode() 155 | # print "*" * 30 156 | # print self.resvmsg 157 | if self.resvmsg.strip( 158 | '\n') is None or self.resvmsg.strip('\n') == "": 159 | continue 160 | elif self.resvmsg.strip('\n') == "quit": 161 | del (userg[self.name]) 162 | self.userlogout(self.name) 163 | break 164 | elif reg.search(self.resvmsg): 165 | self.sendmsgtoone(self.resvmsg, self.name) 166 | elif self.resvmsg.strip('\n') == "w" or self.resvmsg.strip('\n') == "W": 167 | self.whoonline(self.name) 168 | else: 169 | self.sendmsgs(self.resvmsg, self.name) 170 | 171 | def finish(self): 172 | if not self.wfile.closed: 173 | self.wfile.flush() 174 | self.wfile.close() 175 | self.rfile.close() 176 | 177 | 178 | server = MyThreadingTCPServer(srvip, MyTcpHandler) 179 | server.serve_forever() 180 | ``` -------------------------------------------------------------------------------- /exercise/3 变量/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 变量的定义和使用 2 | 3 | 1. 定义两个变量分别为美元和汇率 4 | 2. 通过搜索引擎找到美元兑人民币汇率 5 | 3. 使用Python计算100美元兑换的人民币数量并用print( )进行输出 6 | 7 | -------------------------------------------------------------------------------- /exercise/3 变量/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 变量的定义和使用 2 | 3 | ```python 4 | # 定义美元 5 | dollar = 100 6 | # 定义汇率 7 | exchange = 6.4696 8 | 9 | # 输出结果 10 | print('{dol}美元兑换的人民币数量为{yuan}'.format(dol=dollar, yuan=dollar * exchange)) 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /exercise/4 序列/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 字符串 2 | 3 | 1. 定义一个字符串Hello Python 并使用print( )输出 4 | 2. 定义第二个字符串Let‘s go并使用print( )输出 5 | 3. 定义第三个字符串"The Zen of Python" -- by Tim Peters 并使用print( )输出 6 | 7 | 8 | 9 | # 练习二 字符串基本操作 10 | 11 | 1. 定义两个字符串分别为 xyz 、abc 12 | 2. 对两个字符串进行连接 13 | 3. 取出xyz字符串的第二个和第三个元素 14 | 4. 对abc输出10次 15 | 5. 判断a字符(串)在 xyz 和 abc 两个字符串中是否存在,并进行输出 16 | 17 | 18 | # 练习三 列表的基本操作 19 | 20 | 1. 定义一个含有5个数字的列表 21 | 22 | 2. 为列表增加一个元素 100 23 | 24 | 3. 使用remove()删除一个元素后观察列表的变化 25 | 26 | 4. 使用切片操作分别取出列表的前三个元素,取出列表的最后一个元素 27 | 28 | # 练习四 元组的基本操作 29 | 30 | 1. 定义一个任意元组,对元组使用append() 查看错误信息 31 | 2. 访问元组中的倒数第二个元素 32 | 3. 定义一个新的元组,和 1. 的元组连接成一个新的元组 33 | 4. 计算元组元素个数 34 | 35 | 36 | -------------------------------------------------------------------------------- /exercise/4 序列/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 字符串 2 | 3 | 4 | ```python 5 | # 1. 定义一个字符串Hello Python 并使用print( )输出 6 | string1 = 'Hello Python' 7 | print(string1) 8 | 9 | 10 | # 2. 定义第二个字符串Let‘s go并使用print( )输出 11 | 12 | # 字符串内容包括单引号可以使用双引号将字符串括起来 13 | string2 = "Let's go" 14 | print(string2) 15 | 16 | 17 | # 3. 定义第三个字符串"The Zen of Python" -- by Tim Peters 并使用print( )输出 18 | 19 | string3 = '"The Zen of Python" -- by Tim Peters' 20 | print(string3) 21 | 22 | ``` 23 | 24 | # 练习二 字符串基本操作 25 | 26 | ```python 27 | # 1. 定义两个字符串分别为 xyz 、abc 28 | string1 = 'xyz' 29 | string2 = 'abc' 30 | 31 | # 2. 对两个字符串进行连接 32 | # 字符串属于序列,序列连接操作符为“+” 33 | print(string1 + string2) 34 | 35 | # 3. 取出xyz字符串的第二个和第三个元素 36 | # 序列的切片操作使用“[ ]” 37 | print(string1[1]) 38 | print(string1[2]) 39 | 40 | # 4. 对abc输出10次 41 | # 序列的重复操作 42 | print(string2 * 10) 43 | 44 | # 5. 判断a字符(串)在 xyz 和 abc 两个字符串中是否存在,并进行输出 45 | # 判断字符是否存在于序列当中, 返回布尔值类型,如果存在返回True,不存在返回False 46 | print('a' in string1) 47 | print('a' in string2) 48 | ``` 49 | 50 | 51 | # 练习三 列表的基本操作 52 | 53 | ```python 54 | # 1. 定义一个含有5个数字的列表 55 | list1 = [5, 6, 7, 8, 9] 56 | # 使用type( )可以查看变量的类型 57 | print(type(list1)) 58 | 59 | # 2. 为列表增加一个元素 100 60 | # 列表自带的方法很丰富,参考官方文档 61 | # https://docs.python.org/3.5/library/stdtypes.html#sequence-types-list-tuple-range 62 | list1.append(100) 63 | print(list1) 64 | 65 | # 3. 使用remove()删除一个元素后观察列表的变化 66 | list1.remove(7) 67 | print(list1) 68 | 69 | # 4. 使用切片操作分别取出列表的前三个元素,取出列表的最后一个元素 70 | print(list1[0:3]) 71 | # 注意取出最后一个元素的类型为整型 72 | print(list1[-1]) 73 | 74 | ``` 75 | 76 | 77 | 78 | 79 | 80 | # 练习四 元组的基本操作 81 | 82 | ```python 83 | # 1. 定义一个任意元组,对元组使用append() 查看错误信息 84 | tuple1 = ('x', 'y', 3, 4, 5) 85 | # 元组定义完成一般不可变,也没有append方法,会报错 86 | # AttributeError: 'tuple' object has no attribute 'append' 87 | # tuple1.append() 88 | 89 | # 2. 访问元组中的倒数第二个元素 90 | # 元组也是序列,因此可以使用序列操作 91 | print(tuple1[-2]) 92 | 93 | # 3. 定义一个新的元组,和 1. 的元组连接成一个新的元组 94 | tuple2 = ('a', 'b', 'c') 95 | print(tuple1 + tuple2) 96 | # 组成新的元组之后会新申请一块内存存放元组,操作的两个元组不变 97 | print(tuple1) 98 | print(tuple2) 99 | 100 | # 4. 计算元组元素个数 101 | # 可以使用len( )方法计算,也可以使用自带的__len__( )方法得到元组元素的个数, 102 | # 元组元素的个数和总长度是一样的 103 | print(len(tuple1)) 104 | print(tuple1.__len__()) 105 | ``` 106 | 107 | 108 | -------------------------------------------------------------------------------- /exercise/5 条件和循环/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 条件语句的使用 2 | 3 | 1. 使用if语句判断字符串的长度是否等于10,根据判断结果进行不同的输出 4 | 2. 提示用户输入一个1-40之间的数字,使用if语句根据输入数字的大小进行判断,如果输入的数字在 1-10,11-20,21-30,31-40,分别进行不同的输出 5 | 6 | 7 | 8 | # 练习二 循环语句的使用 9 | 1. 使用for语句输出1-100之间的所有偶数 10 | 2. 使用while语句输出1-100之间能够被3整除的数字 11 | -------------------------------------------------------------------------------- /exercise/5 条件和循环/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 条件语句的使用 2 | 3 | ```python 4 | # 1. 使用if语句判断字符串的长度是否等于10,根据判断结果进行不同的输出 5 | string1 = '123456789' 6 | # 使用len( )可以计算字符串的长度 7 | print(len(string1)) 8 | 9 | # 判断相等可以使用“==”, 不相等可以使用 not 关键字 10 | if not len(string1) == 10: 11 | print('字符串长度不为10') 12 | else: 13 | print('字符串长度为10') 14 | 15 | # 2. 提示用户输入一个1-40之间的数字,使用if语句根据输入数字的大小进行判断,如果输入的数字在 16 | # 1-10,11-20,21-30,31-40,分别进行不同的输出 17 | num_user_input = input('输入一个1-40之间的整数:') 18 | num_to_int = int(num_user_input) 19 | if 1 <= num_to_int <= 10: 20 | print('数字在1-10之间') 21 | elif 11 <= num_to_int <= 20: 22 | print('数字在11-20之间') 23 | elif 21 <= num_to_int <= 30: 24 | print('数字在21-30之间') 25 | else: 26 | print('数字在31-40之间') 27 | ``` 28 | 29 | 30 | # 练习二 循环语句的使用 31 | 32 | ```python 33 | # 1. 使用for语句输出1-100之间的所有偶数 34 | for i in range(1, 101): 35 | if i % 2 == 0: 36 | print(i) 37 | 38 | # 2. 使用while语句输出1-100之间能够被3整除的数字 39 | j = 1 40 | while j <= 100: 41 | if j % 3 == 0: 42 | print(j) 43 | j += 1 44 | 45 | ``` -------------------------------------------------------------------------------- /exercise/6 映射和集合/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 字典的使用 2 | 3 | 1. 定义一个字典,分别使用a、b、c、d作为字典的关键字,值为任意内容 4 | 2. 为该字典增加一个元素‘c':'cake'后,将字典输出到屏幕 5 | 3. 取出字典中关键字为d的值 6 | 7 | 8 | # 练习二 集合的使用 9 | 1. 将字符串hello中每个字符赋值给一个集合,将这个集合输出到屏幕 -------------------------------------------------------------------------------- /exercise/6 映射和集合/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 字典的使用 2 | 3 | ```python 4 | # 1. 定义一个字典,分别使用a、b、c、d作为字典的关键字,值为任意内容 5 | dict1 = {'a': 'aa', 'b': 'xyz', 'c': 'Helo', 'd': 123} 6 | 7 | # 2. 为该字典增加一个元素‘c':'cake'后,将字典输出到屏幕 8 | # 字典的key不能重复,否则会覆盖掉相同key的值 9 | dict1['c'] = 'cake' 10 | print(dict1) 11 | 12 | # 3. 取出字典中关键字为d的值 13 | print(dict1['d']) 14 | ``` 15 | 16 | # 练习二 集合的使用 17 | 18 | ```python 19 | # 1. 将字符串hello中每个字符赋值给一个集合,将这个集合输出到屏幕 20 | str1 = 'hello' 21 | # 集合里的元素不能重复 22 | print(set(str1)) 23 | 24 | ``` -------------------------------------------------------------------------------- /exercise/7 文件和输入输出/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 文件的创建和使用 2 | 1. 创建一个文件,并写入当前日期 3 | 2. 再次打开这个文件,读取文件的前4个字符后退出 4 | 5 | -------------------------------------------------------------------------------- /exercise/7 文件和输入输出/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 文件的创建和使用 2 | ```python 3 | # 1. 创建一个文件,并写入当前日期 4 | import datetime 5 | now = datetime.datetime.now() 6 | with open('c.txt', 'w') as f: 7 | # 注意write( )方法写入的内容是字符串类型 8 | f.write(str(now)) 9 | 10 | 11 | # 2. 再次打开这个文件,读取文件的前4个字符后退出 12 | with open('c.txt', 'r') as f: 13 | text_4 = f.read(4) 14 | print(text_4) 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /exercise/8 错误和异常/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 异常 2 | 1. 在Python程序中,分别使用未定义变量、访问列表不存在的索引、访问字典不存在的关键字观察系统提示的错误信息 3 | 2. 通过Python程序产生IndexError,并用try捕获异常处理 -------------------------------------------------------------------------------- /exercise/8 错误和异常/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 异常 2 | ```python 3 | # 1. 在Python程序中,分别使用未定义变量、访问列表不存在的索引、访问字典不存在的关键字观察系统提示的错误信息 4 | 5 | # 使用未定义变量 6 | a + 1 7 | 8 | # 访问列表不存在的索引 9 | b = ['a', 'b', 'c'] 10 | b[3] 11 | 12 | # 访问字典不存在的key 13 | c = {'x': 1} 14 | c['y'] 15 | 16 | 17 | # 2. 通过Python程序产生IndexError,并用try捕获异常处理 18 | try: 19 | b = ['a', 'b', 'c'] 20 | b[3] 21 | except IndexError: 22 | print('访问列表不存在的索引') 23 | 24 | ``` -------------------------------------------------------------------------------- /exercise/9 函数/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 函数 2 | 1. 创建一个函数,用于接收用户输入的数字,并计算用户输入数字的和 3 | 2. 创建一个函数,传入n个整数,返回其中最大的数和最小的数 4 | 3. 创建一个函数,传入一个参数n,返回n的阶乘 5 | -------------------------------------------------------------------------------- /exercise/9 函数/answer/README.md: -------------------------------------------------------------------------------- 1 | # 练习一 函数 2 | ```python 3 | # 1. 创建一个函数,用于接收用户输入的数字,并计算用户输入数字的和 4 | def func1(): 5 | two_num = input('请输入两个数字,用空格做分隔:') 6 | # 检查用户输入是否合法 7 | func2(two_num) 8 | num1, *_, num2 = list(two_num) 9 | print(int(num1) + int(num2)) 10 | 11 | 12 | def func2(check_number): 13 | pass 14 | 15 | 16 | func1() 17 | 18 | 19 | # 2. 创建一个函数,传入n个整数,返回其中最大的数和最小的数 20 | 21 | 22 | def func3(*nums): 23 | print(max(list(nums))) 24 | print(min(list(nums))) 25 | 26 | 27 | func3(1, 5, 8, 32, 654, 765, 4, 6, 7) 28 | 29 | 30 | # 3. 创建一个函数,传入一个参数n,返回n的阶乘 31 | 32 | 33 | def fact(num3): 34 | if num3 == 0 or num3 == 1: 35 | return 1 36 | else: 37 | return (num3 * fact(num3 - 1)) 38 | 39 | 40 | print(fact(10)) 41 | 42 | 43 | # 使用高阶函数 44 | from functools import reduce 45 | num4 = 10 46 | print(reduce(lambda x, y: x * y, range(1, num4 + 1))) 47 | 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /install_python_windows.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/install_python_windows.pdf -------------------------------------------------------------------------------- /python_demo/.gitignore: -------------------------------------------------------------------------------- 1 | .tox 2 | *.egg-info 3 | chapter.html 4 | -------------------------------------------------------------------------------- /python_demo/04/hello_world.py: -------------------------------------------------------------------------------- 1 | # 这是我的第一个Python程序 2 | 3 | import time # 我导入了一个时间模块 4 | 5 | 6 | print(time.time()) #在屏幕上打印出从1970年1月1日0:00 到现在经过了多少秒 7 | 8 | if 10-9 > 0: 9 | # 这行需要缩进,缩进用4个空格 10 | print('10大于9') -------------------------------------------------------------------------------- /python_demo/04/test1.py: -------------------------------------------------------------------------------- 1 | # 输出一行文字 2 | print('hello time.geerbang!') 3 | 4 | -------------------------------------------------------------------------------- /python_demo/06/network_bandwidth.py: -------------------------------------------------------------------------------- 1 | # 网络带宽计算 2 | # print(100/8) 3 | 4 | bandwidth = 100 5 | ratio = 8 6 | 7 | print(bandwidth/ratio) 8 | 9 | bandWidth 10 | BandWidth 11 | band_width 12 | -------------------------------------------------------------------------------- /python_demo/07/zodiac.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | # u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | # zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | # (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | # 8 | # 9 | # (month, day) = (2, 15) 10 | # 11 | # zodiac_day = filter(lambda x: x<=(month, day), zodiac_days) 12 | # # print(zodiac_day) 13 | # 14 | # zodac_len = len(list(zodiac_day)) % 12 15 | # print(zodiac_name[zodac_len]) 16 | 17 | a_list = ['abc', 'xyz'] 18 | a_list.append('X') 19 | print (a_list) 20 | a_list.remove('xyz') 21 | print(a_list) 22 | 23 | -------------------------------------------------------------------------------- /python_demo/08/zodiac_v2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | 8 | 9 | # 用户输入月份和日期 10 | int_month = int(input('请输入月份:')) 11 | int_day = int(input('请输入日期')) 12 | 13 | # for zd_num in range(len(zodiac_days)): 14 | # if zodiac_days[zd_num] >= (int_month, int_day): 15 | # print(zodiac_name[zd_num]) 16 | # break 17 | # elif int_month == 12 and int_day >23: 18 | # print(zodiac_name[0]) 19 | # break 20 | 21 | n = 0 22 | while zodiac_days[n] < (int_month,int_day): 23 | if int_month == 12 and int_day >23: 24 | break 25 | n += 1 26 | 27 | print(zodiac_name[n]) 28 | 29 | 30 | 31 | 32 | # print(type(str_month)) 33 | # 34 | # zodiac_day = filter(lambda x: x<=(month, day), zodiac_days) 35 | # # print(zodiac_day) 36 | # 37 | # zodac_len = len(list(zodiac_day)) % 12 38 | # print(zodiac_name[zodac_len]) 39 | 40 | -------------------------------------------------------------------------------- /python_demo/10/chinese_zodiac.py: -------------------------------------------------------------------------------- 1 | # 记录生肖,根据年份来判断生肖 2 | 3 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 4 | 5 | # print (chinese_zodiac[0:4] ) 6 | 7 | # print (chinese_zodiac[-1]) 8 | 9 | year = 2018 10 | print (year % 12) 11 | 12 | print (chinese_zodiac[year % 12]) 13 | 14 | print ( '狗' not in chinese_zodiac ) 15 | 16 | print (chinese_zodiac + 'abcd') 17 | 18 | print (chinese_zodiac * 3 ) 19 | -------------------------------------------------------------------------------- /python_demo/10/chinese_zodiac_v2.py: -------------------------------------------------------------------------------- 1 | # 记录生肖,根据年份来判断生肖 2 | 3 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 4 | 5 | # year = int(input('请用户输入出生年份')) 6 | # 7 | # if(chinese_zodiac[year % 12]) == '狗': 8 | # print ('狗年运势。。。') 9 | # 10 | # for cz in chinese_zodiac: 11 | # print(cz) 12 | # 13 | # for i in range(1,13): 14 | # print(i) 15 | # 16 | # for year in range(2000,2019): 17 | # print('%s 年的生肖是 %s' %(year, chinese_zodiac[year % 12])) 18 | # import time 19 | num = 5 20 | while True: 21 | num = num + 1 22 | 23 | if num == 10: 24 | continue 25 | 26 | print(num) 27 | # time.sleep(1) 28 | -------------------------------------------------------------------------------- /python_demo/10/zodiac_v3.py: -------------------------------------------------------------------------------- 1 | 2 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 3 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | 8 | 9 | cz_num = {} 10 | for i in chinese_zodiac: 11 | cz_num[i] = 0 12 | 13 | z_num = {} 14 | for i in zodiac_name: 15 | z_num[i] = 0 16 | 17 | 18 | 19 | 20 | while True: 21 | 22 | # 用户输入出生年份月份和日期 23 | year = int(input('请输入年份:')) 24 | month = int(input('请输入月份:')) 25 | day = int(input('请输入日期:')) 26 | 27 | 28 | n = 0 29 | while zodiac_days[n] < (month,day): 30 | if month == 12 and day >23: 31 | break 32 | n += 1 33 | # 输出生肖和星座 34 | print(zodiac_name[n]) 35 | 36 | 37 | print('%s 年的生肖是 %s' % (year, chinese_zodiac[year % 12])) 38 | 39 | cz_num[chinese_zodiac[year % 12]] += 1 40 | z_num[zodiac_name[n]] += 1 41 | 42 | # 输出生肖和星座的统计信息 43 | for each_key in cz_num.keys(): 44 | print('生肖 %s 有 %d 个'%(each_key,cz_num[each_key])) 45 | 46 | for each_key in z_num.keys(): 47 | print('星座 %s 有 %d 个' %(each_key,z_num[each_key])) 48 | 49 | 50 | -------------------------------------------------------------------------------- /python_demo/12/test_if.py: -------------------------------------------------------------------------------- 1 | x = 'abcd' 2 | if x == 'abc' : 3 | print('x 的值和abc 相等') 4 | else: 5 | print('x和 abc不相等') -------------------------------------------------------------------------------- /python_demo/13/test_for.py: -------------------------------------------------------------------------------- 1 | # 从1 到 10 所有偶数的平方 2 | alist = [] 3 | for i in range(1,11): 4 | if (i % 2 == 0): 5 | alist.append( i*i ) 6 | 7 | 8 | print(alist) 9 | 10 | 11 | blist = [i*i for i in range(1, 11) if(i % 2) == 0] 12 | 13 | print(blist) 14 | 15 | z_num = {} 16 | for i in zodiac_name: 17 | z_num[i] = 0 18 | 19 | z_num = {i:0 for i in zodiac_name} -------------------------------------------------------------------------------- /python_demo/14/test_dict.py: -------------------------------------------------------------------------------- 1 | dict1 = {} 2 | print(type(dict1)) 3 | dict2 = { 'x':1 , 'y':2 } 4 | dict2['z'] = 3 5 | 6 | print(dict2) 7 | 8 | -------------------------------------------------------------------------------- /python_demo/19/file_op.py: -------------------------------------------------------------------------------- 1 | # 将小说的主要人物记录在文件中 2 | # file1 = open('name.txt','w') 3 | # file1.write('诸葛亮') 4 | # file1.close() 5 | # 6 | # 7 | # file2 = open('name.txt') 8 | # print(file2.read()) 9 | # 10 | # file2.close() 11 | # 12 | # file3 = open('name.txt','a') 13 | # file3.write('刘备') 14 | # file3.close() 15 | # 16 | # file4 = open('name.txt') 17 | # print (file4.readline()) 18 | # 19 | # file5 = open('name.txt') 20 | # for line in file5.readlines(): 21 | # print(line) 22 | # print('=====') 23 | # 24 | # 25 | 26 | file6 = open('name.txt') 27 | print('当前文件指针的位置 %s' %file6.tell()) 28 | print ( '当前读取到了一个字符,字符的内容是 %s' %file6.read(1)) 29 | print('当前文件指针的位置 %s' %file6.tell()) 30 | # 第一个参数代表偏移位置,第二个参数 0 表示从文件开头偏移 1表示从当前位置偏移, 2 从文件结尾 31 | file6.seek(5,0) 32 | print('我们进行了seek操作') 33 | print('当前文件指针的位置 %s' %file6.tell()) 34 | print ( '当前读取到了一个字符,字符的内容是 %s' %file6.read(1)) 35 | print('当前文件指针的位置 %s' %file6.tell()) 36 | file6.close() 37 | -------------------------------------------------------------------------------- /python_demo/21/exception_handling.py: -------------------------------------------------------------------------------- 1 | # i = j 2 | 3 | 4 | # print()) 5 | 6 | 7 | # a='123' 8 | # print(a[3]) 9 | # 10 | # d = {'a':1 ,'b':2} 11 | # print(d['c']) 12 | 13 | # 14 | # year = int(input('input year:')) 15 | 16 | # try: 17 | # year = int(input('input year:')) 18 | # except ValueError: 19 | # print('年份要输入数字') 20 | # 21 | # a=123 22 | # a.append() 23 | 24 | # except (ValueError, AttributeError, KeyError) 25 | 26 | # 27 | # try: 28 | # print(1/'a') 29 | # except Exception as e: 30 | # print(' %s' %e) 31 | # 32 | # try: 33 | # raise NameError('helloError') 34 | # except NameError: 35 | # print('my custom error') 36 | 37 | 38 | try: 39 | a = open('name.txt') 40 | except Exception as e: 41 | print(e) 42 | 43 | finally: 44 | a.close() 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /python_demo/22/func_test.py: -------------------------------------------------------------------------------- 1 | # print('abc',end='\n') 2 | # print('abc') 3 | # 4 | # def func (a, b, c): 5 | # print('a= %s' %a) 6 | # print('b= %s' %b) 7 | # print('c= %s' %c) 8 | # 9 | # 10 | # func(1, c=3) 11 | 12 | 13 | 14 | # # 取得参数的个数 15 | # def howlong(first, *other): 16 | # print( 1 + len(other)) 17 | # 18 | # howlong() 19 | 20 | # 21 | # var1 = 123 22 | # 23 | # def func(): 24 | # global var1 25 | # var1 = 456 26 | # print(var1) 27 | # 28 | # 29 | # 30 | # func() 31 | # print(var1) 32 | 33 | # iter() next() 34 | 35 | # list1 =[1, 2, 3] 36 | # it = iter(list1) 37 | # # print( next(it)) 38 | # # print( next(it)) 39 | # # print( next(it)) 40 | # # print( next(it)) # except 41 | # # 42 | # 43 | # 44 | # 45 | # # for i in range(10,20,0.5): 46 | # # print(i) 47 | # # 48 | # # def frange(start, stop, step): 49 | # # x = start 50 | # # while x < stop: 51 | # # yield x 52 | # # x += step 53 | # # 54 | # # 55 | # # for i in frange(10,20,0.5): 56 | # # print(i) 57 | # # 58 | # # 59 | # # 60 | # # 61 | # # 62 | # # 63 | # # def true():return True 64 | # # lambda : True 65 | # # 66 | # # 67 | # # >>> def add(x,y): 68 | # # ... return x+y 69 | # # ... 70 | # # 71 | # # >>> def add(x,y): return x+y 72 | # # lambda x,y: x+y 73 | # # 74 | # # 75 | # # >>> add(3,5) 76 | # # 8 77 | # # >>> 78 | # 79 | # 80 | # 81 | # # lambda x:x<= (month, day) 82 | # # 83 | # # def func1(x): 84 | # # return x<= (month, day) 85 | # # 86 | # # 87 | # # 88 | # # lambda item:item[1] 89 | # # 90 | # # def func2(item): 91 | # # return item[1] 92 | # # 93 | # # 94 | # # filter() map() reduce() zip() 95 | # # 96 | # 97 | # 98 | # a=[1,2,3,4,5,6,7] 99 | # list(filter(lambda x:x>2 , a)) 100 | # 101 | # >>> help(filter) 102 | # 103 | # >>> a=[1,2,3,4,5,6,7] 104 | # >>> list(filter(lambda x:x>2 , a)) 105 | # [3, 4, 5, 6, 7] 106 | # >>> help(map) 107 | # 108 | # >>> a=[1,2,3] 109 | # >>> map(lambda x:x ,a) 110 | # 111 | # >>> list(map(lambda x:x ,a)) 112 | # [1, 2, 3] 113 | # >>> list(map(lambda x:x+1 ,a)) 114 | # [2, 3, 4] 115 | # >>> b=[4,5,6] 116 | # >>> list(map(lambda x,y:x+y ,a,b)) 117 | # [5, 7, 9] 118 | # >>> 119 | # >>> 120 | # >>> 121 | # >>> 122 | # >>> 123 | # >>> [1, 2, 3] 124 | # [1, 2, 3] 125 | # >>> [4, 5, 6] 126 | # [4, 5, 6] 127 | # >>> help(reduce) 128 | # Traceback (most recent call last): 129 | # File "", line 1, in 130 | # NameError: name 'reduce' is not defined 131 | # >>> from functools import reduce 132 | # 133 | # 134 | # >>> from functools import reduce 135 | # >>> reduce(lambda x,y: x+y ,[2,3,4],1 ) 136 | # 10 137 | # >>> ((1+2)+3)+4 138 | # 139 | # >>> for i in zip((1,2,3),(4,5,6)): 140 | # ... print(i) 141 | # ... 142 | # (1, 4) 143 | # (2, 5) 144 | # (3, 6) 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | def func(): 174 | a = 1 175 | b = 2 176 | return a+b 177 | 178 | 179 | def sum(a): 180 | def add(b): 181 | return a+b 182 | 183 | return add 184 | 185 | # add 函数名称或函数的引用 186 | # add() 函数的调用 187 | 188 | num1 = func() 189 | 190 | num2 = sum(2) 191 | print( num2(4)) 192 | 193 | # 194 | # print(type(num1)) 195 | # print(type(num2)) 196 | # 197 | 198 | count() 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /python_demo/26/name.txt: -------------------------------------------------------------------------------- 1 | 諸葛亮|關羽|劉備|曹操|孫權|關羽|張飛|呂布|周瑜|趙雲|龐統|司馬懿|黃忠|馬超 -------------------------------------------------------------------------------- /python_demo/26/sanguo.py: -------------------------------------------------------------------------------- 1 | 2 | # 读取人物名称 3 | f = open('name.txt') 4 | data = f.read() 5 | data0 = data.split('|') 6 | 7 | # 读取兵器名称 8 | f2 = open('weapon.txt') 9 | # data2 = f2.read() 10 | i = 1 11 | for line in f2.readlines(): 12 | if i % 2 == 1: 13 | print(line.strip('\n')) 14 | i += 1 15 | 16 | f3 = open('sanguo.txt',encoding='GB18030') 17 | print(f3.read().replace('\n','')) 18 | # 19 | # 20 | # def func(filename): 21 | # print(open(filename).read()) 22 | # print('test func') 23 | # 24 | # 25 | # 26 | # func('name.txt') 27 | -------------------------------------------------------------------------------- /python_demo/26/sanguo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/26/sanguo.txt -------------------------------------------------------------------------------- /python_demo/26/sanguo_v2.py: -------------------------------------------------------------------------------- 1 | import re 2 | def find_item( hero ): 3 | with open('sanguo.txt',encoding='GB18030') as f: 4 | data = f.read().replace('\n','') 5 | name_num = re.findall(hero,data) 6 | # print('主角 %s 出现 %s 次' %(hero, len(name_num))) 7 | 8 | return len(name_num) 9 | 10 | 11 | 12 | 13 | # 读取人物的信息 14 | name_dict = {} 15 | with open('name.txt') as f: 16 | for line in f: 17 | names = line.split('|') 18 | for n in names: 19 | # print(n) 20 | name_num = find_item(n) 21 | name_dict[n] = name_num 22 | 23 | name_sorted = sorted(name_dict.items(), key=lambda item: item[1], reverse=True) 24 | print(name_sorted[0:10]) -------------------------------------------------------------------------------- /python_demo/26/sanguo_v3.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def find_main_charecters(charecter_name): 5 | with open('sanguo.txt', encoding='gb18030') as f: 6 | data = f.read().replace("\n", "") 7 | name_num = re.findall(charecter_name, data) 8 | # print('主角 %s 出现了%s 次'%(charecter_name,len(name_num))) 9 | return charecter_name, len(name_num) 10 | 11 | 12 | name_dict = {} 13 | with open('name.txt', encoding='utf-8') as f: 14 | for line in f: 15 | names = line.split('|') 16 | for n in names: 17 | char_name, char_number = find_main_charecters(n) 18 | name_dict[char_name] = char_number 19 | 20 | weapon_dict = {} 21 | with open('weapon.txt', encoding='utf-8') as f: 22 | i = 1 23 | for line in f: 24 | if i%2 == 1: 25 | weapon_name, weapon_number = find_main_charecters(line.strip()) 26 | weapon_dict[weapon_name] = weapon_number 27 | i = i+1 28 | 29 | 30 | name_sorted = sorted(name_dict.items(), key=lambda item: item[1], reverse=True) 31 | print(name_sorted[0:10]) 32 | 33 | weapon_sorted = sorted(weapon_dict.items(), key=lambda item: item[1], reverse=True) 34 | print(weapon_sorted[0:10]) -------------------------------------------------------------------------------- /python_demo/26/weapon.txt: -------------------------------------------------------------------------------- 1 | 青龍偃月刀 2 | 3 | 丈八點鋼矛 4 | 5 | 鐵脊蛇矛 6 | 7 | 涯角槍 8 | 9 | 諸葛槍 10 | 11 | 方天畫戟 12 | 13 | 長柄鐵錘 14 | 15 | 鐵蒺藜骨朵 16 | 17 | 大斧 18 | 19 | 蘸金斧 20 | 21 | 三尖刀 22 | 23 | 截頭大刀 24 | 25 | 馬岱寶刀 26 | 27 | 古錠刀 28 | 29 | 衠鋼槊 30 | 31 | 丈八長標 32 | 33 | 王雙大刀 34 | 35 | 呂虔刀 36 | 37 | 龍泉劍 38 | 39 | 倚天劍 40 | 41 | 青釭 42 | 43 | 七寶刀 44 | 45 | 雙股劍 46 | 47 | 松紋廂寶劍 48 | 49 | 孟德劍 50 | 51 | 思召劍 52 | 53 | 飛景三劍 54 | 55 | 文士劍 56 | 57 | 蜀八劍 58 | 59 | 鎮山劍 60 | 61 | 吳六劍 62 | 63 | 皇帝吳王劍 64 | 65 | 日月刀 66 | 67 | 百辟寶刀 68 | 69 | 龍鱗刀 70 | 71 | 百辟匕首二 72 | 73 | 鐵鞭 74 | 75 | 鋼鞭 76 | 77 | 四楞鐵簡 78 | 79 | 雙鐵戟 80 | 81 | 諸葛連弩 82 | 83 | 寶雕弓 84 | 85 | 鵲畫弓 86 | 87 | 虎筋弦弓 88 | 89 | 兩石力之弓 90 | 91 | 手戟 92 | 93 | 短戟 94 | 95 | 飛石 96 | 97 | 流星錘 98 | 99 | 銅撾 100 | -------------------------------------------------------------------------------- /python_demo/28/func_test2.py: -------------------------------------------------------------------------------- 1 | def counter(FIRST=0): 2 | cnt = [FIRST] 3 | 4 | def add_one(): 5 | cnt[0] += 1 6 | return cnt[0] 7 | 8 | return add_one 9 | 10 | 11 | num5 = counter(5) 12 | num10 = counter(10) 13 | 14 | print(num5()) 15 | print(num5()) 16 | print(num5()) 17 | print(num10()) 18 | print(num10()) 19 | -------------------------------------------------------------------------------- /python_demo/29/func_test3.py: -------------------------------------------------------------------------------- 1 | # a * x + b = y 2 | 3 | def a_line(a,b): 4 | def arg_y(x): 5 | return a*x+b 6 | return arg_y 7 | 8 | 9 | def a_line(a,b): 10 | return lambda x: a*x+b 11 | return arg_y 12 | 13 | 14 | # a=3 b=5 15 | # x=10 y=? 16 | # x=20 y =? 17 | 18 | # a=5 b=10 19 | 20 | line1 = a_line(3, 5) 21 | line2 = a_line(5,10) 22 | 23 | print (line1(10)) 24 | print (line1(20)) 25 | 26 | #def func1( a,b, x) 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /python_demo/30/func_test4.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | # print( time.time()) 4 | 5 | def timmer(func): 6 | def wrapper(): 7 | start_time = time.time() 8 | func() 9 | stop_time = time.time() 10 | print("运行时间是 %s 秒 " % (stop_time - start_time)) 11 | return wrapper 12 | 13 | 14 | 15 | @timmer 16 | def i_can_sleep(): 17 | time.sleep(3) 18 | 19 | 20 | 21 | 22 | # start_time = time.time() 23 | i_can_sleep() 24 | 25 | # stop_time = time.time() 26 | 27 | # print('函数运行了 %s 秒' %(stop_time-start_time)) 28 | -------------------------------------------------------------------------------- /python_demo/31/func_test5.py: -------------------------------------------------------------------------------- 1 | def new_tips(argv): 2 | def tips(func): 3 | def nei(a, b): 4 | print('start %s %s' % (argv, func.__name__)) 5 | func(a, b) 6 | print('stop') 7 | 8 | return nei 9 | return tips 10 | 11 | 12 | @new_tips('add_module') 13 | def add(a, b): 14 | print(a + b) 15 | 16 | 17 | @new_tips('sub_module') 18 | def sub(a, b): 19 | print(a - b) 20 | 21 | 22 | print(add(4, 5)) 23 | print(sub(7, 3)) 24 | -------------------------------------------------------------------------------- /python_demo/32/func_test6.py: -------------------------------------------------------------------------------- 1 | fd = open('name.txt') 2 | try: 3 | for line in fd: 4 | print (line) 5 | finally: 6 | fd.close() 7 | 8 | 9 | with open('name.txt') as f: 10 | for line in f: 11 | print(line) 12 | -------------------------------------------------------------------------------- /python_demo/33/mod_test.py: -------------------------------------------------------------------------------- 1 | import mymod 2 | 3 | mymod.print_me() -------------------------------------------------------------------------------- /python_demo/33/mymod.py: -------------------------------------------------------------------------------- 1 | def print_me(): 2 | print('me') 3 | 4 | 5 | # print_me() 6 | 7 | https://www.python.org/dev/peps/pep-0008/ 8 | 9 | 10 | 11 | pycharm 安装PEP8 12 | cmd窗口输入:pip install autopep8 13 | Tools→Extends Tools→点击加号 14 | 15 | Name:Autopep8(可以随便取) 16 | - Tools settings: 17 | - Programs:`autopep8` (前提是你已经安装了哦) 18 | - Parameters:`--in-place --aggressive --aggressive $FilePath$` 19 | - Working directory:`$ProjectFileDir$` 20 | - 点击Output Filters→添加,在对话框中的:Regular expression to match output中输入:`$FILE_PATH$\:$LINE$\:$COLUMN$\:.*` 21 | 22 | -------------------------------------------------------------------------------- /python_demo/35/class_test.py: -------------------------------------------------------------------------------- 1 | # user1 = {'name':'tom','hp':100} 2 | # user2 = {'name':'jerry','hp':80} 3 | # 4 | # def print_role(rolename): 5 | # print('name is %s ,hp is %s' %(rolename['name'], rolename['hp']) ) 6 | # 7 | # print_role(user1) 8 | 9 | 10 | class Player(): #定义一个类 11 | def __init__(self, name, hp, occu): 12 | self.__name = name # 变量被称作属性 13 | self.hp = hp 14 | self.occu = occu 15 | def print_role(self): #定义一个方法 16 | print('%s: %s %s' %(self.__name,self.hp,self.occu)) 17 | 18 | def updateName(self,newname): 19 | self.name = newname 20 | 21 | 22 | 23 | class Monster(): 24 | '定义怪物类' 25 | def __init__(self,hp=100): 26 | self.hp = hp 27 | def run(self): 28 | print('移动到某个位置') 29 | 30 | def whoami(self): 31 | print('我是怪物父类') 32 | class Animals(Monster): 33 | '普通怪物' 34 | def __init__(self,hp=10): 35 | super().__init__(hp) 36 | 37 | 38 | class Boss(Monster): 39 | 'Boss类怪物' 40 | def __init__(self,hp=1000): 41 | super().__init__(hp) 42 | def whoami(self): 43 | print('我是怪物我怕谁') 44 | 45 | a1 = Monster(200) 46 | print(a1.hp) 47 | print(a1.run()) 48 | a2 = Animals(1) 49 | print(a2.hp) 50 | print(a2.run()) 51 | 52 | a3 = Boss(800) 53 | a3.whoami() 54 | 55 | print('a1的类型 %s' %type(a1)) 56 | print('a2的类型 %s' %type(a2)) 57 | print('a3的类型 %s' %type(a3)) 58 | 59 | print(isinstance(a2,Monster)) 60 | # 61 | # user1 = Player('tom',100,'war') #类的实例化 62 | # user2 = Player('jerry',90,'master') 63 | # user1.print_role() 64 | # user2.print_role() 65 | # 66 | # 67 | # user1.updateName('wilson') 68 | # user1.print_role() 69 | # user1.__name = ('aaa') 70 | # user1.print_role() -------------------------------------------------------------------------------- /python_demo/38/with_test.py: -------------------------------------------------------------------------------- 1 | class Testwith(object): 2 | ''' 3 | with 包含了 __enter__ 和 __exit__ 方法 4 | ''' 5 | 6 | def __enter__(self): 7 | print('run now ') 8 | 9 | def __exit__(self, exc_type, exc_val, exc_tb): 10 | if exc_tb is None: 11 | print('exit normal ') 12 | else: 13 | print('exit with exception') 14 | 15 | 16 | with Testwith(): 17 | print('test') 18 | raise NameError('Exception') -------------------------------------------------------------------------------- /python_demo/39/thread_test.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | from threading import current_thread 4 | 5 | def myThread(arg1, arg2): 6 | print(current_thread().getName(),'start') 7 | print('%s %s'%(arg1, arg2)) 8 | time.sleep(1) 9 | print(current_thread().getName(),'stop') 10 | 11 | 12 | for i in range(1,6,1): 13 | # t1 = myThread(i, i+1) 14 | t1 = threading.Thread(target=myThread,args=(i, i+1)) 15 | t1.start() 16 | 17 | print(current_thread().getName(),'end') 18 | -------------------------------------------------------------------------------- /python_demo/39/thread_testv2.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from threading import current_thread 3 | 4 | class Mythread(threading.Thread): 5 | def run(self): 6 | print(current_thread().getName(),'start') 7 | print('run') 8 | print(current_thread().getName(),'stop') 9 | 10 | 11 | t1 = Mythread() 12 | t1.start() 13 | t1.join() 14 | 15 | print(current_thread().getName(),'end') 16 | -------------------------------------------------------------------------------- /python_demo/40/con_cus.py: -------------------------------------------------------------------------------- 1 | from threading import Thread,current_thread 2 | import time 3 | import random 4 | from queue import Queue 5 | 6 | queue = Queue(5) 7 | 8 | class ProducerThread(Thread): 9 | def run(self): 10 | name = current_thread().getName() 11 | nums = range(100) 12 | global queue 13 | while True: 14 | num = random.choice(nums) 15 | queue.put(num) 16 | print('生产者 %s 生产了数据 %s' %(name, num)) 17 | t = random.randint(1,3) 18 | time.sleep(t) 19 | print('生产者 %s 睡眠了 %s 秒' %(name, t)) 20 | 21 | class ConsumerTheard(Thread): 22 | def run(self): 23 | name = current_thread().getName() 24 | global queue 25 | while True: 26 | num = queue.get() 27 | queue.task_done() 28 | print('消费者 %s 消耗了数据 %s' %(name, num)) 29 | t = random.randint(1,5) 30 | time.sleep(t) 31 | print('消费者 %s 睡眠了 %s 秒' % (name, t)) 32 | 33 | 34 | p1 = ProducerThread(name = 'p1') 35 | p1.start() 36 | p2 = ProducerThread(name = 'p2') 37 | p2.start() 38 | p3 = ProducerThread(name = 'p3') 39 | p3.start() 40 | c1 = ConsumerTheard(name = 'c1') 41 | c1.start() 42 | c2 = ConsumerTheard(name = 'c2') 43 | c2.start() -------------------------------------------------------------------------------- /python_demo/41/stdlib_test.py: -------------------------------------------------------------------------------- 1 | # 日常应用比较广泛的模块是: 2 | # 1. 文字处理的 re 3 | # 2. 日期类型的time、datetime 4 | # 3. 数字和数学类型的math、random 5 | # 4. 文件和目录访问的pathlib、os.path 6 | # 5. 数据压缩和归档的tarfile 7 | # 6. 通用操作系统的os、logging、argparse 8 | # 7. 多线程的 threading、queue 9 | # 8. Internet数据处理的 base64 、json、urllib 10 | # 9. 结构化标记处理工具的 html、xml 11 | # 10. 开发工具的unitest 12 | # 11. 调试工具的 timeit 13 | # 12. 软件包发布的venv 14 | # 13. 运行服务的__main__ 15 | 16 | 17 | # . ^ $ * + ? {m} {m,n} [] | \d \D \s () 18 | # ^$ 19 | # .*? 20 | 21 | import re 22 | 23 | 24 | p = re.compile(r'(\d+)-(\d+)-(\d+)') 25 | # print (p.match('aa2018-05-10bb').group(2) ) 26 | # print (p.match('2018-05-10').groups() ) 27 | # 28 | # year, month, day = p.match('2018-05-10').groups() 29 | # print(year) 30 | # 31 | # print (p.search('aa2018-05-10bb')) 32 | # phone = '123-456-789 # 这是电话号码' 33 | # p2 = re.sub(r'#.*$','',phone) 34 | # print(p2) 35 | # p3 = re.sub(r'\D','',p2) 36 | # print(p3) 37 | # findall() 38 | 39 | import random 40 | print( random.randint(1,5)) 41 | print( random.choice(['aa','bb','cc'])) -------------------------------------------------------------------------------- /python_demo/47/time_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | # print(time.time()) 3 | # print(time.localtime()) 4 | # print(time.strftime('%Y%m%d')) 5 | 6 | 7 | import datetime 8 | print(datetime.datetime.now()) 9 | newtime = datetime.timedelta(minutes=10) 10 | print(datetime.datetime.now()+ newtime) 11 | 12 | one_day=datetime.datetime(2008,5,27) 13 | new_date=datetime.timedelta(days=10) 14 | print( one_day + new_date) -------------------------------------------------------------------------------- /python_demo/49/dir_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | print( os.path.abspath('..')) 3 | print( os.path.exists('/Users')) 4 | print( os.path.isdir('/Users')) 5 | os.path.join('/tmp/a/','b/c') 6 | 7 | from pathlib import Path 8 | p = Path('.') 9 | print ( p.resolve()) 10 | 11 | p.is_dir() 12 | 13 | q = Path('/tmp/a/b/c') 14 | 15 | Path.mkdir(q,parents=True) 16 | 17 | -------------------------------------------------------------------------------- /python_demo/51/numpy_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | arr1 =np.array([2,3,4]) 4 | 5 | # print( arr1) 6 | # print ( arr1.dtype) 7 | # 8 | # arr2 = np.array([ 1.2, 2.3 , 3.4]) 9 | # 10 | # print( arr2) 11 | # print( arr2.dtype) 12 | # 13 | # print ( arr1 + arr2) 14 | # 15 | # print( arr2 * 10 ) 16 | # 17 | # 18 | # data = [[1,2,3], [4,5,6]] 19 | # arr3 = np.array(data) 20 | # print( arr3) 21 | # print ( arr3.dtype) 22 | # 23 | # print (np.zeros((3,5))) 24 | # 25 | # print( np.ones((4,6))) 26 | # 27 | # print(np.empty((2,3,2))) 28 | 29 | arr4 = np.arange(10) 30 | 31 | arr4[5:8] = 10 32 | 33 | print(arr4) 34 | 35 | arr_slice = arr4[5:8].copy() 36 | 37 | arr_slice[:] = 15 38 | 39 | print(arr_slice) 40 | print(arr4) -------------------------------------------------------------------------------- /python_demo/55/iris_test.csv: -------------------------------------------------------------------------------- 1 | 30,4,setosa,versicolor,virginica 2 | 5.9,3.0,4.2,1.5,1 3 | 6.9,3.1,5.4,2.1,2 4 | 5.1,3.3,1.7,0.5,0 5 | 6.0,3.4,4.5,1.6,1 6 | 5.5,2.5,4.0,1.3,1 7 | 6.2,2.9,4.3,1.3,1 8 | 5.5,4.2,1.4,0.2,0 9 | 6.3,2.8,5.1,1.5,2 10 | 5.6,3.0,4.1,1.3,1 11 | 6.7,2.5,5.8,1.8,2 12 | 7.1,3.0,5.9,2.1,2 13 | 4.3,3.0,1.1,0.1,0 14 | 5.6,2.8,4.9,2.0,2 15 | 5.5,2.3,4.0,1.3,1 16 | 6.0,2.2,4.0,1.0,1 17 | 5.1,3.5,1.4,0.2,0 18 | 5.7,2.6,3.5,1.0,1 19 | 4.8,3.4,1.9,0.2,0 20 | 5.1,3.4,1.5,0.2,0 21 | 5.7,2.5,5.0,2.0,2 22 | 5.4,3.4,1.7,0.2,0 23 | 5.6,3.0,4.5,1.5,1 24 | 6.3,2.9,5.6,1.8,2 25 | 6.3,2.5,4.9,1.5,1 26 | 5.8,2.7,3.9,1.2,1 27 | 6.1,3.0,4.6,1.4,1 28 | 5.2,4.1,1.5,0.1,0 29 | 6.7,3.1,4.7,1.5,1 30 | 6.7,3.3,5.7,2.5,2 31 | 6.4,2.9,4.3,1.3,1 32 | -------------------------------------------------------------------------------- /python_demo/55/iris_training.csv: -------------------------------------------------------------------------------- 1 | 120,4,setosa,versicolor,virginica 2 | 6.4,2.8,5.6,2.2,2 3 | 5.0,2.3,3.3,1.0,1 4 | 4.9,2.5,4.5,1.7,2 5 | 4.9,3.1,1.5,0.1,0 6 | 5.7,3.8,1.7,0.3,0 7 | 4.4,3.2,1.3,0.2,0 8 | 5.4,3.4,1.5,0.4,0 9 | 6.9,3.1,5.1,2.3,2 10 | 6.7,3.1,4.4,1.4,1 11 | 5.1,3.7,1.5,0.4,0 12 | 5.2,2.7,3.9,1.4,1 13 | 6.9,3.1,4.9,1.5,1 14 | 5.8,4.0,1.2,0.2,0 15 | 5.4,3.9,1.7,0.4,0 16 | 7.7,3.8,6.7,2.2,2 17 | 6.3,3.3,4.7,1.6,1 18 | 6.8,3.2,5.9,2.3,2 19 | 7.6,3.0,6.6,2.1,2 20 | 6.4,3.2,5.3,2.3,2 21 | 5.7,4.4,1.5,0.4,0 22 | 6.7,3.3,5.7,2.1,2 23 | 6.4,2.8,5.6,2.1,2 24 | 5.4,3.9,1.3,0.4,0 25 | 6.1,2.6,5.6,1.4,2 26 | 7.2,3.0,5.8,1.6,2 27 | 5.2,3.5,1.5,0.2,0 28 | 5.8,2.6,4.0,1.2,1 29 | 5.9,3.0,5.1,1.8,2 30 | 5.4,3.0,4.5,1.5,1 31 | 6.7,3.0,5.0,1.7,1 32 | 6.3,2.3,4.4,1.3,1 33 | 5.1,2.5,3.0,1.1,1 34 | 6.4,3.2,4.5,1.5,1 35 | 6.8,3.0,5.5,2.1,2 36 | 6.2,2.8,4.8,1.8,2 37 | 6.9,3.2,5.7,2.3,2 38 | 6.5,3.2,5.1,2.0,2 39 | 5.8,2.8,5.1,2.4,2 40 | 5.1,3.8,1.5,0.3,0 41 | 4.8,3.0,1.4,0.3,0 42 | 7.9,3.8,6.4,2.0,2 43 | 5.8,2.7,5.1,1.9,2 44 | 6.7,3.0,5.2,2.3,2 45 | 5.1,3.8,1.9,0.4,0 46 | 4.7,3.2,1.6,0.2,0 47 | 6.0,2.2,5.0,1.5,2 48 | 4.8,3.4,1.6,0.2,0 49 | 7.7,2.6,6.9,2.3,2 50 | 4.6,3.6,1.0,0.2,0 51 | 7.2,3.2,6.0,1.8,2 52 | 5.0,3.3,1.4,0.2,0 53 | 6.6,3.0,4.4,1.4,1 54 | 6.1,2.8,4.0,1.3,1 55 | 5.0,3.2,1.2,0.2,0 56 | 7.0,3.2,4.7,1.4,1 57 | 6.0,3.0,4.8,1.8,2 58 | 7.4,2.8,6.1,1.9,2 59 | 5.8,2.7,5.1,1.9,2 60 | 6.2,3.4,5.4,2.3,2 61 | 5.0,2.0,3.5,1.0,1 62 | 5.6,2.5,3.9,1.1,1 63 | 6.7,3.1,5.6,2.4,2 64 | 6.3,2.5,5.0,1.9,2 65 | 6.4,3.1,5.5,1.8,2 66 | 6.2,2.2,4.5,1.5,1 67 | 7.3,2.9,6.3,1.8,2 68 | 4.4,3.0,1.3,0.2,0 69 | 7.2,3.6,6.1,2.5,2 70 | 6.5,3.0,5.5,1.8,2 71 | 5.0,3.4,1.5,0.2,0 72 | 4.7,3.2,1.3,0.2,0 73 | 6.6,2.9,4.6,1.3,1 74 | 5.5,3.5,1.3,0.2,0 75 | 7.7,3.0,6.1,2.3,2 76 | 6.1,3.0,4.9,1.8,2 77 | 4.9,3.1,1.5,0.1,0 78 | 5.5,2.4,3.8,1.1,1 79 | 5.7,2.9,4.2,1.3,1 80 | 6.0,2.9,4.5,1.5,1 81 | 6.4,2.7,5.3,1.9,2 82 | 5.4,3.7,1.5,0.2,0 83 | 6.1,2.9,4.7,1.4,1 84 | 6.5,2.8,4.6,1.5,1 85 | 5.6,2.7,4.2,1.3,1 86 | 6.3,3.4,5.6,2.4,2 87 | 4.9,3.1,1.5,0.1,0 88 | 6.8,2.8,4.8,1.4,1 89 | 5.7,2.8,4.5,1.3,1 90 | 6.0,2.7,5.1,1.6,1 91 | 5.0,3.5,1.3,0.3,0 92 | 6.5,3.0,5.2,2.0,2 93 | 6.1,2.8,4.7,1.2,1 94 | 5.1,3.5,1.4,0.3,0 95 | 4.6,3.1,1.5,0.2,0 96 | 6.5,3.0,5.8,2.2,2 97 | 4.6,3.4,1.4,0.3,0 98 | 4.6,3.2,1.4,0.2,0 99 | 7.7,2.8,6.7,2.0,2 100 | 5.9,3.2,4.8,1.8,1 101 | 5.1,3.8,1.6,0.2,0 102 | 4.9,3.0,1.4,0.2,0 103 | 4.9,2.4,3.3,1.0,1 104 | 4.5,2.3,1.3,0.3,0 105 | 5.8,2.7,4.1,1.0,1 106 | 5.0,3.4,1.6,0.4,0 107 | 5.2,3.4,1.4,0.2,0 108 | 5.3,3.7,1.5,0.2,0 109 | 5.0,3.6,1.4,0.2,0 110 | 5.6,2.9,3.6,1.3,1 111 | 4.8,3.1,1.6,0.2,0 112 | 6.3,2.7,4.9,1.8,2 113 | 5.7,2.8,4.1,1.3,1 114 | 5.0,3.0,1.6,0.2,0 115 | 6.3,3.3,6.0,2.5,2 116 | 5.0,3.5,1.6,0.6,0 117 | 5.5,2.6,4.4,1.2,1 118 | 5.7,3.0,4.2,1.2,1 119 | 4.4,2.9,1.4,0.2,0 120 | 4.8,3.0,1.4,0.1,0 121 | 5.5,2.4,3.7,1.0,1 122 | -------------------------------------------------------------------------------- /python_demo/55/pandas_test.py: -------------------------------------------------------------------------------- 1 | from pandas import Series, DataFrame 2 | import pandas as pd 3 | 4 | 5 | obj = Series([4, 5, 6, -7]) 6 | 7 | # print(obj) 8 | # 9 | # print( obj.index) 10 | # 11 | # print ( obj.values) 12 | # 13 | # 14 | # {['a']:1} 15 | # 16 | 17 | obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'c', 'a']) 18 | 19 | # print(obj2) 20 | # 21 | # obj2['c'] = 6 22 | # 23 | # print(obj2) 24 | # 25 | # print ('f' in obj2) 26 | 27 | 28 | sdata = { 29 | 'beijing': 35000, 30 | 'shanghai': 71000, 31 | 'guangzhou': 16000, 32 | 'shenzhen': 5000} 33 | obj3 = Series(sdata) 34 | # print( obj3) 35 | 36 | obj3.index = ['bj', 'gz', 'sh', 'sz'] 37 | # 38 | # print( obj3) 39 | 40 | 41 | data = {'city': ['shanghai', 'shanghai', 'shanghai', 'beijing', 'beijing'], 42 | 'year': [2016, 2017, 2018, 2017, 2018], 43 | 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 44 | 45 | frame = DataFrame(data) 46 | 47 | frame2 = DataFrame(data, columns=['year', 'city', 'pop']) 48 | 49 | 50 | # print(frame) 51 | # 52 | # print(frame2) 53 | # 54 | # print(frame2['city']) 55 | # print(frame2.year) 56 | frame2['new'] = 100 57 | 58 | # print(frame2) 59 | 60 | frame2['cap'] = frame2.city == 'beijing' 61 | 62 | # print( frame2) 63 | 64 | pop = {'beijing': {2008: 1.5, 2009: 2.0}, 65 | 'shanghai': {2008: 2.0, 2009: 3.6} 66 | } 67 | 68 | frame3 = DataFrame(pop) 69 | print(frame3.T) 70 | 71 | obj4 = Series([4.5, 7.2, -5.3, 3.6], index=['b', 'd', 'c', 'a']) 72 | 73 | obj5 = obj4.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0) 74 | 75 | print(obj5) 76 | 77 | obj6 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4]) 78 | 79 | # 80 | # print( obj6.reindex(range(6),method='bfill')) 81 | 82 | from numpy import nan as NA 83 | 84 | data = Series([1, NA, 2]) 85 | # print(data.dropna()) 86 | 87 | # data2 = DataFrame([[1., 6.5, 3], [1., NA, NA], [NA, NA, NA] 88 | # ]) 89 | # data2[4] = NA 90 | # print(data2) 91 | # print(data2.dropna(axis=1, how='all')) 92 | # 93 | # data2.fillna(0) 94 | # print(data2.fillna(0, inplace=True)) 95 | # print(data2) 96 | 97 | import numpy as np 98 | 99 | data3 = Series(np.random.randn(10), 100 | index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'], 101 | [1, 2, 3, 1, 2, 3, 1, 2, 2, 3]]) 102 | 103 | print( data3.unstack().stack() ) 104 | 105 | # print ( data3['b':'c']) 106 | -------------------------------------------------------------------------------- /python_demo/59/plt_test.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | # 3 | # #绘制简单的曲线 4 | # plt.plot([1, 3, 5], [4, 8, 10]) 5 | # plt.show() 6 | 7 | import numpy as np 8 | 9 | # x= np.linspace(-np.pi,np.pi,100) # x轴的定义域为 -3.14~3.14,中间间隔100个元素 10 | # plt.plot(x,np.sin(x)) 11 | # #显示所画的图 12 | # plt.show() 13 | 14 | # x = np.linspace(-np.pi * 2, np.pi * 2, 100) # 定义域为: -2pi 到 2pi 15 | # plt.figure(1, dpi=50) # 创建图表1 16 | # for i in range(1, 5): # 画四条线 17 | # plt.plot(x, np.sin(x / i)) 18 | # plt.show() 19 | # 20 | # plt.figure(1, dpi=50) # 创建图表1,dpi代表图片精细度,dpi越大文件越大,杂志要300以上 21 | # data = [1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 4] 22 | # plt.hist(data) # 只要传入数据,直方图就会统计数据出现的次数 23 | # 24 | # plt.show() 25 | 26 | # x = np.arange(1,10) 27 | # y = x 28 | # fig = plt.figure() 29 | # plt.scatter(x,y,c = 'r',marker = 'o') #c = 'r'表示散点的颜色为红色,marker 表示指定三点多形状为圆形 30 | # plt.show() 31 | 32 | 33 | # import matplotlib.pyplot as plt 34 | # import numpy as np 35 | # import pandas as pd 36 | # 37 | # iris = pd.read_csv("./iris_training.csv") 38 | # print (iris.head() ) 39 | # 40 | # #绘制散点图 41 | # iris.plot(kind="scatter", x="120", y="4") 42 | # 43 | # # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 44 | # plt.show() 45 | # 46 | # import matplotlib.pyplot as plt 47 | # import numpy as np 48 | # import pandas as pd 49 | # import seaborn as sns 50 | # 51 | # iris = pd.read_csv("./iris_training.csv") 52 | # #设置样式 53 | # sns.set(style="white", color_codes=True) 54 | # # 设置绘制格式为散点图 55 | # sns.jointplot(x="120", y="4", data=iris, size=5) 56 | # # distplot绘制曲线 57 | # sns.distplot(iris['120']) 58 | # 59 | # # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 60 | # plt.show() 61 | 62 | import matplotlib.pyplot as plt 63 | import pandas as pd 64 | import seaborn as sns 65 | 66 | import warnings 67 | warnings.filterwarnings("ignore") 68 | 69 | iris = pd.read_csv("./iris_training.csv") 70 | 71 | sns.set(style="white", color_codes=True) 72 | 73 | 74 | # FacetGrid 一般绘图函数 75 | # hue 彩色显示分类0/1/2 76 | # plt.scatter 绘制散点图 77 | # add_legend() 显示分类的描述信息 78 | # sns.FacetGrid(iris, hue="virginica", size=5).map(plt.scatter, "120", "4").add_legend() 79 | 80 | sns.FacetGrid(iris, hue="virginica", size=5).map(plt.scatter, "setosa", "versicolor").add_legend() 81 | # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 82 | plt.show() -------------------------------------------------------------------------------- /python_demo/62/pachong1.py: -------------------------------------------------------------------------------- 1 | from urllib import request 2 | 3 | url ='http://www.baidu.com' 4 | response = request.urlopen(url,timeout=1) 5 | print (response.read().decode('utf-8')) 6 | -------------------------------------------------------------------------------- /python_demo/63/pachong2.py: -------------------------------------------------------------------------------- 1 | from urllib import parse 2 | from urllib import request 3 | 4 | data = bytes(parse.urlencode({'word':'hello'}),encoding='utf8') 5 | # print(data) 6 | 7 | response = request.urlopen('http://httpbin.org/post', data=data) 8 | print(response.read().decode('utf-8')) 9 | 10 | 11 | response2 = request.urlopen('http://httpbin.org/get', timeout=1) 12 | print(response2.read()) 13 | 14 | 15 | # response3 = request.urlopen('http://httpbin.org/get', timeout=0.1) 16 | 17 | import urllib 18 | import socket 19 | 20 | 21 | try: 22 | response3 = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1) 23 | except urllib.error.URLError as e: 24 | if isinstance(e.reason, socket.timeout): 25 | print('TIME OUT') -------------------------------------------------------------------------------- /python_demo/64/pachong3.py: -------------------------------------------------------------------------------- 1 | from urllib import request, parse 2 | 3 | url = 'http://httpbin.org/post' 4 | 5 | headers = { 6 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 7 | "Accept-Encoding": "gzip, deflate, sdch", 8 | "Accept-Language": "zh-CN,zh;q=0.8", 9 | "Connection": "close", 10 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 11 | "Referer": "http://httpbin.org/", 12 | "Upgrade-Insecure-Requests": "1", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 14 | } 15 | 16 | dict = { 17 | 'name': 'value' 18 | } 19 | 20 | data = bytes(parse.urlencode(dict), encoding='utf8') 21 | req = request.Request(url=url, data=data, headers=headers, method='POST') 22 | response = request.urlopen(req) 23 | print(response.read().decode('utf-8')) -------------------------------------------------------------------------------- /python_demo/65/pachong4.py: -------------------------------------------------------------------------------- 1 | # get请求 2 | import requests 3 | url = 'http://httpbin.org/get' 4 | data = {'key': 'value', 'abc': 'xyz'} 5 | # .get是使用get方式请求url,字典类型的data不用进行额外处理 6 | response = requests.get(url, data) 7 | print(response.text) 8 | 9 | 10 | # post请求 11 | import requests 12 | url = 'http://httpbin.org/post' 13 | data = {'key': 'value', 'abc': 'xyz'} 14 | # .post表示为post方法 15 | response = requests.post(url, data) 16 | # 返回类型为json格式 17 | print(response.json()) -------------------------------------------------------------------------------- /python_demo/66/pachong5.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import re 3 | content = requests.get('http://www.cnu.cc/discoveryPage/hot-人像').text 4 | 5 | # print(content) 6 | 7 | 8 | # < div class ="grid-item work-thumbnail" > 9 | # < a href="(.*?)".*?title">(.*?) 10 | # < div class ="author" > LynnWei < / div > 11 | 12 | pattern = re.compile(r'(.*?)', re.S) 13 | results = re.findall(pattern, content) 14 | # print(results) 15 | 16 | 17 | for result in results: 18 | url, name = result 19 | print(url, re.sub('\s', '', name)) -------------------------------------------------------------------------------- /python_demo/69/pachong6.py: -------------------------------------------------------------------------------- 1 | html_doc = """ 2 | The Dormouse's story 3 | 4 |

The Dormouse's story

5 | 6 |

Once upon a time there were three little sisters; and their names were 7 | Elsie, 8 | Lacie and 9 | Tillie; 10 | and they lived at the bottom of a well.

11 | 12 |

...

13 | """ 14 | 15 | from bs4 import BeautifulSoup 16 | 17 | soup = BeautifulSoup(html_doc, 'lxml') 18 | 19 | print(soup.prettify()) 20 | 21 | # 22 | # # 找到title标签 23 | # print(soup.title) 24 | # 25 | # # title 标签里的内容 26 | # print(soup.title.string) 27 | 28 | 29 | # # 找到p标签 30 | print(soup.p) 31 | # 32 | # # 找到p标签class的名字 33 | # print(soup.p['class']) 34 | # 35 | # # 找到第一个a标签 36 | # print(soup.a) 37 | # 38 | # # 找到所有的a标签 39 | # print(soup.find_all('a')) 40 | # 41 | # 42 | # # 找到id为link3的的标签 43 | print(soup.find(id="link3")) 44 | # 45 | # # 找到所有标签的链接 46 | # for link in soup.find_all('a'): 47 | # print(link.get('href')) 48 | # 49 | # # 找到文档中所有的文本内容 50 | # print(soup.get_text()) -------------------------------------------------------------------------------- /python_demo/69/pachong_infoq.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | 4 | headers = { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Language": "zh-CN,zh;q=0.8", 7 | "Connection": "close", 8 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 9 | "Referer": "http://www.infoq.com", 10 | "Upgrade-Insecure-Requests": "1", 11 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 12 | } 13 | 14 | url = 'https://www.infoq.com/news/' 15 | 16 | # 取得网页完整内容 17 | 18 | 19 | def craw(url): 20 | response = requests.get(url, headers=headers) 21 | print(response.text) 22 | 23 | # craw(url) 24 | 25 | # 取得新闻标题 26 | 27 | 28 | def craw2(url): 29 | response = requests.get(url, headers=headers) 30 | 31 | soup = BeautifulSoup(response.text, 'lxml') 32 | 33 | for title_href in soup.find_all('div', class_='items__content'): 34 | print([title.get('title') 35 | for title in title_href.find_all('a') if title.get('title')]) 36 | 37 | # craw2(url) 38 | 39 | 40 | # 翻页 41 | for i in range(15, 46, 15): 42 | url = 'http://www.infoq.com/news/' + str(i) 43 | # print(url) 44 | craw2(url) 45 | -------------------------------------------------------------------------------- /python_demo/70/pachong7.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | 4 | headers = { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Language": "zh-CN,zh;q=0.8", 7 | "Connection": "close", 8 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 9 | "Referer": "http://www.infoq.com", 10 | "Upgrade-Insecure-Requests": "1", 11 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 12 | } 13 | 14 | url = 'http://www.infoq.com/cn/news' 15 | 16 | 17 | 18 | # 取得新闻标题 19 | def craw2(url): 20 | response = requests.get(url, headers=headers) 21 | 22 | soup = BeautifulSoup(response.text, 'lxml') 23 | 24 | for title_href in soup.find_all('div', class_='news_type_block'): 25 | print([title.get('title') 26 | for title in title_href.find_all('a') if title.get('title')]) 27 | 28 | # craw2(url) 29 | 30 | 31 | 32 | # 翻页 33 | for i in range(15, 46, 15): 34 | url = 'http://www.infoq.com/cn/news/' + str(i) 35 | # print(url) 36 | craw2(url) -------------------------------------------------------------------------------- /python_demo/70/pachong_infoq2.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | import os 4 | import shutil 5 | 6 | headers = { 7 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 8 | "Accept-Language": "zh-CN,zh;q=0.8", 9 | "Connection": "close", 10 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 11 | "Referer": "http://www.infoq.com", 12 | "Upgrade-Insecure-Requests": "1", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 14 | } 15 | 16 | url = 'http://www.infoq.com/presentations' 17 | 18 | 19 | # 下载图片 20 | # Requests 库封装复杂的接口,提供更人性化的 HTTP 客户端,但不直接提供下载文件的函数。 21 | # 需要通过为请求设置特殊参数 stream 来实现。当 stream 设为 True 时, 22 | # 上述请求只下载HTTP响应头,并保持连接处于打开状态, 23 | # 直到访问 Response.content 属性时才开始下载响应主体内容 24 | 25 | 26 | def download_jpg(image_url, image_localpath): 27 | response = requests.get(image_url, stream=True) 28 | if response.status_code == 200: 29 | with open(image_localpath, 'wb') as f: 30 | response.raw.deconde_content = True 31 | shutil.copyfileobj(response.raw, f) 32 | 33 | 34 | # 取得演讲图片 35 | def craw3(url): 36 | response = requests.get(url, headers=headers) 37 | soup = BeautifulSoup(response.text, 'lxml') 38 | for pic_href in soup.find_all('div', class_='items__content'): 39 | for pic in pic_href.find_all('img'): 40 | imgurl = pic.get('src') 41 | dir = os.path.abspath('.') 42 | filename = os.path.basename(imgurl) 43 | imgpath = os.path.join(dir, filename) 44 | print('开始下载 %s' % imgurl) 45 | download_jpg(imgurl, imgpath) 46 | 47 | 48 | # craw3(url) 49 | 50 | # 翻页 51 | j = 0 52 | for i in range(12, 37, 12): 53 | url = 'http://www.infoq.com/presentations' + str(i) 54 | j += 1 55 | print('第 %d 页' % j) 56 | craw3(url) 57 | -------------------------------------------------------------------------------- /python_demo/71/code/Makefile: -------------------------------------------------------------------------------- 1 | chapter.html: chapter.md 2 | pandoc -s -o chapter.html chapter.md 3 | 4 | clean: 5 | find . -name \*.pyc -delete 6 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dbdb.interface import DBDB 4 | 5 | 6 | __all__ = ['DBDB', 'connect'] 7 | 8 | 9 | def connect(dbname): 10 | try: 11 | f = open(dbname, 'r+b') 12 | except IOError: 13 | fd = os.open(dbname, os.O_RDWR | os.O_CREAT) 14 | f = os.fdopen(fd, 'r+b') 15 | return DBDB(f) 16 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | 3 | 4 | from dbdb.logical import LogicalBase, ValueRef 5 | 6 | 7 | class BinaryNode(object): 8 | @classmethod 9 | def from_node(cls, node, **kwargs): 10 | length = node.length 11 | if 'left_ref' in kwargs: 12 | length += kwargs['left_ref'].length - node.left_ref.length 13 | if 'right_ref' in kwargs: 14 | length += kwargs['right_ref'].length - node.right_ref.length 15 | 16 | return cls( 17 | left_ref=kwargs.get('left_ref', node.left_ref), 18 | key=kwargs.get('key', node.key), 19 | value_ref=kwargs.get('value_ref', node.value_ref), 20 | right_ref=kwargs.get('right_ref', node.right_ref), 21 | length=length, 22 | ) 23 | 24 | def __init__(self, left_ref, key, value_ref, right_ref, length): 25 | self.left_ref = left_ref 26 | self.key = key 27 | self.value_ref = value_ref 28 | self.right_ref = right_ref 29 | self.length = length 30 | 31 | def store_refs(self, storage): 32 | self.value_ref.store(storage) 33 | self.left_ref.store(storage) 34 | self.right_ref.store(storage) 35 | 36 | 37 | class BinaryNodeRef(ValueRef): 38 | def prepare_to_store(self, storage): 39 | if self._referent: 40 | self._referent.store_refs(storage) 41 | 42 | @property 43 | def length(self): 44 | if self._referent is None and self._address: 45 | raise RuntimeError('Asking for BinaryNodeRef length of unloaded node') 46 | if self._referent: 47 | return self._referent.length 48 | else: 49 | return 0 50 | 51 | @staticmethod 52 | def referent_to_string(referent): 53 | return pickle.dumps({ 54 | 'left': referent.left_ref.address, 55 | 'key': referent.key, 56 | 'value': referent.value_ref.address, 57 | 'right': referent.right_ref.address, 58 | 'length': referent.length, 59 | }) 60 | 61 | @staticmethod 62 | def string_to_referent(string): 63 | d = pickle.loads(string) 64 | return BinaryNode( 65 | BinaryNodeRef(address=d['left']), 66 | d['key'], 67 | ValueRef(address=d['value']), 68 | BinaryNodeRef(address=d['right']), 69 | d['length'], 70 | ) 71 | 72 | 73 | class BinaryTree(LogicalBase): 74 | node_ref_class = BinaryNodeRef 75 | 76 | def _get(self, node, key): 77 | while node is not None: 78 | if key < node.key: 79 | node = self._follow(node.left_ref) 80 | elif node.key < key: 81 | node = self._follow(node.right_ref) 82 | else: 83 | return self._follow(node.value_ref) 84 | raise KeyError 85 | 86 | def _insert(self, node, key, value_ref): 87 | if node is None: 88 | new_node = BinaryNode( 89 | self.node_ref_class(), key, value_ref, self.node_ref_class(), 1) 90 | elif key < node.key: 91 | new_node = BinaryNode.from_node( 92 | node, 93 | left_ref=self._insert( 94 | self._follow(node.left_ref), key, value_ref)) 95 | elif node.key < key: 96 | new_node = BinaryNode.from_node( 97 | node, 98 | right_ref=self._insert( 99 | self._follow(node.right_ref), key, value_ref)) 100 | else: 101 | new_node = BinaryNode.from_node(node, value_ref=value_ref) 102 | return self.node_ref_class(referent=new_node) 103 | 104 | def _delete(self, node, key): 105 | if node is None: 106 | raise KeyError 107 | elif key < node.key: 108 | new_node = BinaryNode.from_node( 109 | node, 110 | left_ref=self._delete( 111 | self._follow(node.left_ref), key)) 112 | elif node.key < key: 113 | new_node = BinaryNode.from_node( 114 | node, 115 | right_ref=self._delete( 116 | self._follow(node.right_ref), key)) 117 | else: 118 | left = self._follow(node.left_ref) 119 | right = self._follow(node.right_ref) 120 | if left and right: 121 | replacement = self._find_max(left) 122 | left_ref = self._delete( 123 | self._follow(node.left_ref), replacement.key) 124 | new_node = BinaryNode( 125 | left_ref, 126 | replacement.key, 127 | replacement.value_ref, 128 | node.right_ref, 129 | left_ref.length + node.right_ref.length + 1, 130 | ) 131 | elif left: 132 | return node.left_ref 133 | else: 134 | return node.right_ref 135 | return self.node_ref_class(referent=new_node) 136 | 137 | def _find_max(self, node): 138 | while True: 139 | next_node = self._follow(node.right_ref) 140 | if next_node is None: 141 | return node 142 | node = next_node 143 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/interface.py: -------------------------------------------------------------------------------- 1 | from dbdb.binary_tree import BinaryTree 2 | from dbdb.physical import Storage 3 | 4 | 5 | class DBDB(object): 6 | 7 | def __init__(self, f): 8 | self._storage = Storage(f) 9 | self._tree = BinaryTree(self._storage) 10 | 11 | def _assert_not_closed(self): 12 | if self._storage.closed: 13 | raise ValueError('Database closed.') 14 | 15 | def close(self): 16 | self._storage.close() 17 | 18 | def commit(self): 19 | self._assert_not_closed() 20 | self._tree.commit() 21 | 22 | def __getitem__(self, key): 23 | self._assert_not_closed() 24 | return self._tree.get(key) 25 | 26 | def __setitem__(self, key, value): 27 | self._assert_not_closed() 28 | return self._tree.set(key, value) 29 | 30 | def __delitem__(self, key): 31 | self._assert_not_closed() 32 | return self._tree.pop(key) 33 | 34 | def __contains__(self, key): 35 | try: 36 | self[key] 37 | except KeyError: 38 | return False 39 | else: 40 | return True 41 | 42 | def __len__(self): 43 | return len(self._tree) 44 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/logical.py: -------------------------------------------------------------------------------- 1 | class ValueRef(object): 2 | def prepare_to_store(self, storage): 3 | pass 4 | 5 | @staticmethod 6 | def referent_to_string(referent): 7 | return referent.encode('utf-8') 8 | 9 | @staticmethod 10 | def string_to_referent(string): 11 | return string.decode('utf-8') 12 | 13 | def __init__(self, referent=None, address=0): 14 | self._referent = referent 15 | self._address = address 16 | 17 | @property 18 | def address(self): 19 | return self._address 20 | 21 | def get(self, storage): 22 | if self._referent is None and self._address: 23 | self._referent = self.string_to_referent(storage.read(self._address)) 24 | return self._referent 25 | 26 | def store(self, storage): 27 | if self._referent is not None and not self._address: 28 | self.prepare_to_store(storage) 29 | self._address = storage.write(self.referent_to_string(self._referent)) 30 | 31 | 32 | class LogicalBase(object): 33 | node_ref_class = None 34 | value_ref_class = ValueRef 35 | 36 | def __init__(self, storage): 37 | self._storage = storage 38 | self._refresh_tree_ref() 39 | 40 | def commit(self): 41 | self._tree_ref.store(self._storage) 42 | self._storage.commit_root_address(self._tree_ref.address) 43 | 44 | def _refresh_tree_ref(self): 45 | self._tree_ref = self.node_ref_class( 46 | address=self._storage.get_root_address()) 47 | 48 | def get(self, key): 49 | if not self._storage.locked: 50 | self._refresh_tree_ref() 51 | return self._get(self._follow(self._tree_ref), key) 52 | 53 | def set(self, key, value): 54 | if self._storage.lock(): 55 | self._refresh_tree_ref() 56 | self._tree_ref = self._insert( 57 | self._follow(self._tree_ref), key, self.value_ref_class(value)) 58 | 59 | def pop(self, key): 60 | if self._storage.lock(): 61 | self._refresh_tree_ref() 62 | self._tree_ref = self._delete( 63 | self._follow(self._tree_ref), key) 64 | 65 | def _follow(self, ref): 66 | return ref.get(self._storage) 67 | 68 | def __len__(self): 69 | if not self._storage.locked: 70 | self._refresh_tree_ref() 71 | root = self._follow(self._tree_ref) 72 | if root: 73 | return root.length 74 | else: 75 | return 0 76 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/physical.py: -------------------------------------------------------------------------------- 1 | # This started as a very thin wrapper around a file object, with intent to 2 | # provide an object address on write() and a superblock. But as I was writing 3 | # it, I realised that the user really wouldn't want to deal with the lengths of 4 | # the writen chunks (and Pickle won't do it for you), so this module would have 5 | # to abstract the file object into it's own degenerate key/value store. 6 | # (Degenerate because you can't pick the keys, and it never releases storage, 7 | # even when it becomes unreachable!) 8 | 9 | import os 10 | import struct 11 | 12 | import portalocker 13 | 14 | 15 | class Storage(object): 16 | SUPERBLOCK_SIZE = 4096 17 | INTEGER_FORMAT = "!Q" 18 | INTEGER_LENGTH = 8 19 | 20 | def __init__(self, f): 21 | self._f = f 22 | self.locked = False 23 | self._ensure_superblock() 24 | 25 | def _ensure_superblock(self): 26 | self.lock() 27 | self._seek_end() 28 | end_address = self._f.tell() 29 | if end_address < self.SUPERBLOCK_SIZE: 30 | self._f.write(b'\x00' * (self.SUPERBLOCK_SIZE - end_address)) 31 | self.unlock() 32 | 33 | def lock(self): 34 | if not self.locked: 35 | portalocker.lock(self._f, portalocker.LOCK_EX) 36 | self.locked = True 37 | return True 38 | else: 39 | return False 40 | 41 | def unlock(self): 42 | if self.locked: 43 | self._f.flush() 44 | portalocker.unlock(self._f) 45 | self.locked = False 46 | 47 | def _seek_end(self): 48 | self._f.seek(0, os.SEEK_END) 49 | 50 | def _seek_superblock(self): 51 | self._f.seek(0) 52 | 53 | def _bytes_to_integer(self, integer_bytes): 54 | return struct.unpack(self.INTEGER_FORMAT, integer_bytes)[0] 55 | 56 | def _integer_to_bytes(self, integer): 57 | return struct.pack(self.INTEGER_FORMAT, integer) 58 | 59 | def _read_integer(self): 60 | return self._bytes_to_integer(self._f.read(self.INTEGER_LENGTH)) 61 | 62 | def _write_integer(self, integer): 63 | self.lock() 64 | self._f.write(self._integer_to_bytes(integer)) 65 | 66 | def write(self, data): 67 | self.lock() 68 | self._seek_end() 69 | object_address = self._f.tell() 70 | self._write_integer(len(data)) 71 | self._f.write(data) 72 | return object_address 73 | 74 | def read(self, address): 75 | self._f.seek(address) 76 | length = self._read_integer() 77 | data = self._f.read(length) 78 | return data 79 | 80 | def commit_root_address(self, root_address): 81 | self.lock() 82 | self._f.flush() 83 | self._seek_superblock() 84 | self._write_integer(root_address) 85 | self._f.flush() 86 | self.unlock() 87 | 88 | def get_root_address(self): 89 | self._seek_superblock() 90 | root_address = self._read_integer() 91 | return root_address 92 | 93 | def close(self): 94 | self.unlock() 95 | self._f.close() 96 | 97 | @property 98 | def closed(self): 99 | return self._f.closed 100 | -------------------------------------------------------------------------------- /python_demo/71/code/build/lib/dbdb/tool.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | import dbdb 5 | 6 | 7 | OK = 0 8 | BAD_ARGS = 1 9 | BAD_VERB = 2 10 | BAD_KEY = 3 11 | 12 | 13 | def usage(): 14 | print("Usage:", file=sys.stderr) 15 | print("\tpython -m dbdb.tool DBNAME get KEY", file=sys.stderr) 16 | print("\tpython -m dbdb.tool DBNAME set KEY VALUE", file=sys.stderr) 17 | print("\tpython -m dbdb.tool DBNAME delete KEY", file=sys.stderr) 18 | 19 | 20 | def main(argv): 21 | if not (4 <= len(argv) <= 5): 22 | usage() 23 | return BAD_ARGS 24 | dbname, verb, key, value = (argv[1:] + [None])[:4] 25 | if verb not in {'get', 'set', 'delete'}: 26 | usage() 27 | return BAD_VERB 28 | db = dbdb.connect(dbname) 29 | try: 30 | if verb == 'get': 31 | sys.stdout.write(db[key]) 32 | elif verb == 'set': 33 | db[key] = value 34 | db.commit() 35 | else: 36 | del db[key] 37 | db.commit() 38 | except KeyError: 39 | print("Key not found", file=sys.stderr) 40 | return BAD_KEY 41 | return OK 42 | 43 | 44 | if __name__ == '__main__': 45 | sys.exit(main(sys.argv)) 46 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dbdb.interface import DBDB 4 | 5 | 6 | __all__ = ['DBDB', 'connect'] 7 | 8 | 9 | def connect(dbname): 10 | try: 11 | f = open(dbname, 'r+b') 12 | except IOError: 13 | fd = os.open(dbname, os.O_RDWR | os.O_CREAT) 14 | f = os.fdopen(fd, 'r+b') 15 | return DBDB(f) 16 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/binary_tree.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/binary_tree.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/interface.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/interface.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/logical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/logical.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/physical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/physical.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/__pycache__/tool.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/__pycache__/tool.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | 3 | 4 | from dbdb.logical import LogicalBase, ValueRef 5 | 6 | 7 | class BinaryNode(object): 8 | @classmethod 9 | def from_node(cls, node, **kwargs): 10 | length = node.length 11 | if 'left_ref' in kwargs: 12 | length += kwargs['left_ref'].length - node.left_ref.length 13 | if 'right_ref' in kwargs: 14 | length += kwargs['right_ref'].length - node.right_ref.length 15 | 16 | return cls( 17 | left_ref=kwargs.get('left_ref', node.left_ref), 18 | key=kwargs.get('key', node.key), 19 | value_ref=kwargs.get('value_ref', node.value_ref), 20 | right_ref=kwargs.get('right_ref', node.right_ref), 21 | length=length, 22 | ) 23 | 24 | def __init__(self, left_ref, key, value_ref, right_ref, length): 25 | self.left_ref = left_ref 26 | self.key = key 27 | self.value_ref = value_ref 28 | self.right_ref = right_ref 29 | self.length = length 30 | 31 | def store_refs(self, storage): 32 | self.value_ref.store(storage) 33 | self.left_ref.store(storage) 34 | self.right_ref.store(storage) 35 | 36 | 37 | class BinaryNodeRef(ValueRef): 38 | def prepare_to_store(self, storage): 39 | if self._referent: 40 | self._referent.store_refs(storage) 41 | 42 | @property 43 | def length(self): 44 | if self._referent is None and self._address: 45 | raise RuntimeError('Asking for BinaryNodeRef length of unloaded node') 46 | if self._referent: 47 | return self._referent.length 48 | else: 49 | return 0 50 | 51 | @staticmethod 52 | def referent_to_string(referent): 53 | return pickle.dumps({ 54 | 'left': referent.left_ref.address, 55 | 'key': referent.key, 56 | 'value': referent.value_ref.address, 57 | 'right': referent.right_ref.address, 58 | 'length': referent.length, 59 | }) 60 | 61 | @staticmethod 62 | def string_to_referent(string): 63 | d = pickle.loads(string) 64 | return BinaryNode( 65 | BinaryNodeRef(address=d['left']), 66 | d['key'], 67 | ValueRef(address=d['value']), 68 | BinaryNodeRef(address=d['right']), 69 | d['length'], 70 | ) 71 | 72 | 73 | class BinaryTree(LogicalBase): 74 | node_ref_class = BinaryNodeRef 75 | 76 | def _get(self, node, key): 77 | while node is not None: 78 | if key < node.key: 79 | node = self._follow(node.left_ref) 80 | elif node.key < key: 81 | node = self._follow(node.right_ref) 82 | else: 83 | return self._follow(node.value_ref) 84 | raise KeyError 85 | 86 | def _insert(self, node, key, value_ref): 87 | if node is None: 88 | new_node = BinaryNode( 89 | self.node_ref_class(), key, value_ref, self.node_ref_class(), 1) 90 | elif key < node.key: 91 | new_node = BinaryNode.from_node( 92 | node, 93 | left_ref=self._insert( 94 | self._follow(node.left_ref), key, value_ref)) 95 | elif node.key < key: 96 | new_node = BinaryNode.from_node( 97 | node, 98 | right_ref=self._insert( 99 | self._follow(node.right_ref), key, value_ref)) 100 | else: 101 | new_node = BinaryNode.from_node(node, value_ref=value_ref) 102 | return self.node_ref_class(referent=new_node) 103 | 104 | def _delete(self, node, key): 105 | if node is None: 106 | raise KeyError 107 | elif key < node.key: 108 | new_node = BinaryNode.from_node( 109 | node, 110 | left_ref=self._delete( 111 | self._follow(node.left_ref), key)) 112 | elif node.key < key: 113 | new_node = BinaryNode.from_node( 114 | node, 115 | right_ref=self._delete( 116 | self._follow(node.right_ref), key)) 117 | else: 118 | left = self._follow(node.left_ref) 119 | right = self._follow(node.right_ref) 120 | if left and right: 121 | replacement = self._find_max(left) 122 | left_ref = self._delete( 123 | self._follow(node.left_ref), replacement.key) 124 | new_node = BinaryNode( 125 | left_ref, 126 | replacement.key, 127 | replacement.value_ref, 128 | node.right_ref, 129 | left_ref.length + node.right_ref.length + 1, 130 | ) 131 | elif left: 132 | return node.left_ref 133 | else: 134 | return node.right_ref 135 | return self.node_ref_class(referent=new_node) 136 | 137 | def _find_max(self, node): 138 | while True: 139 | next_node = self._follow(node.right_ref) 140 | if next_node is None: 141 | return node 142 | node = next_node 143 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/interface.py: -------------------------------------------------------------------------------- 1 | from dbdb.binary_tree import BinaryTree 2 | from dbdb.physical import Storage 3 | 4 | 5 | class DBDB(object): 6 | 7 | def __init__(self, f): 8 | self._storage = Storage(f) 9 | self._tree = BinaryTree(self._storage) 10 | 11 | def _assert_not_closed(self): 12 | if self._storage.closed: 13 | raise ValueError('Database closed.') 14 | 15 | def close(self): 16 | self._storage.close() 17 | 18 | def commit(self): 19 | self._assert_not_closed() 20 | self._tree.commit() 21 | 22 | def __getitem__(self, key): 23 | self._assert_not_closed() 24 | return self._tree.get(key) 25 | 26 | def __setitem__(self, key, value): 27 | self._assert_not_closed() 28 | return self._tree.set(key, value) 29 | 30 | def __delitem__(self, key): 31 | self._assert_not_closed() 32 | return self._tree.pop(key) 33 | 34 | def __contains__(self, key): 35 | try: 36 | self[key] 37 | except KeyError: 38 | return False 39 | else: 40 | return True 41 | 42 | def __len__(self): 43 | return len(self._tree) 44 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/logical.py: -------------------------------------------------------------------------------- 1 | class ValueRef(object): 2 | def prepare_to_store(self, storage): 3 | pass 4 | 5 | @staticmethod 6 | def referent_to_string(referent): 7 | return referent.encode('utf-8') 8 | 9 | @staticmethod 10 | def string_to_referent(string): 11 | return string.decode('utf-8') 12 | 13 | def __init__(self, referent=None, address=0): 14 | self._referent = referent 15 | self._address = address 16 | 17 | @property 18 | def address(self): 19 | return self._address 20 | 21 | def get(self, storage): 22 | if self._referent is None and self._address: 23 | self._referent = self.string_to_referent(storage.read(self._address)) 24 | return self._referent 25 | 26 | def store(self, storage): 27 | if self._referent is not None and not self._address: 28 | self.prepare_to_store(storage) 29 | self._address = storage.write(self.referent_to_string(self._referent)) 30 | 31 | 32 | class LogicalBase(object): 33 | node_ref_class = None 34 | value_ref_class = ValueRef 35 | 36 | def __init__(self, storage): 37 | self._storage = storage 38 | self._refresh_tree_ref() 39 | 40 | def commit(self): 41 | self._tree_ref.store(self._storage) 42 | self._storage.commit_root_address(self._tree_ref.address) 43 | 44 | def _refresh_tree_ref(self): 45 | self._tree_ref = self.node_ref_class( 46 | address=self._storage.get_root_address()) 47 | 48 | def get(self, key): 49 | if not self._storage.locked: 50 | self._refresh_tree_ref() 51 | return self._get(self._follow(self._tree_ref), key) 52 | 53 | def set(self, key, value): 54 | if self._storage.lock(): 55 | self._refresh_tree_ref() 56 | self._tree_ref = self._insert( 57 | self._follow(self._tree_ref), key, self.value_ref_class(value)) 58 | 59 | def pop(self, key): 60 | if self._storage.lock(): 61 | self._refresh_tree_ref() 62 | self._tree_ref = self._delete( 63 | self._follow(self._tree_ref), key) 64 | 65 | def _follow(self, ref): 66 | return ref.get(self._storage) 67 | 68 | def __len__(self): 69 | if not self._storage.locked: 70 | self._refresh_tree_ref() 71 | root = self._follow(self._tree_ref) 72 | if root: 73 | return root.length 74 | else: 75 | return 0 76 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/physical.py: -------------------------------------------------------------------------------- 1 | # This started as a very thin wrapper around a file object, with intent to 2 | # provide an object address on write() and a superblock. But as I was writing 3 | # it, I realised that the user really wouldn't want to deal with the lengths of 4 | # the writen chunks (and Pickle won't do it for you), so this module would have 5 | # to abstract the file object into it's own degenerate key/value store. 6 | # (Degenerate because you can't pick the keys, and it never releases storage, 7 | # even when it becomes unreachable!) 8 | 9 | import os 10 | import struct 11 | 12 | import portalocker 13 | 14 | 15 | class Storage(object): 16 | SUPERBLOCK_SIZE = 4096 17 | INTEGER_FORMAT = "!Q" 18 | INTEGER_LENGTH = 8 19 | 20 | def __init__(self, f): 21 | self._f = f 22 | self.locked = False 23 | self._ensure_superblock() 24 | 25 | def _ensure_superblock(self): 26 | self.lock() 27 | self._seek_end() 28 | end_address = self._f.tell() 29 | if end_address < self.SUPERBLOCK_SIZE: 30 | self._f.write(b'\x00' * (self.SUPERBLOCK_SIZE - end_address)) 31 | self.unlock() 32 | 33 | def lock(self): 34 | if not self.locked: 35 | portalocker.lock(self._f, portalocker.LOCK_EX) 36 | self.locked = True 37 | return True 38 | else: 39 | return False 40 | 41 | def unlock(self): 42 | if self.locked: 43 | self._f.flush() 44 | portalocker.unlock(self._f) 45 | self.locked = False 46 | 47 | def _seek_end(self): 48 | self._f.seek(0, os.SEEK_END) 49 | 50 | def _seek_superblock(self): 51 | self._f.seek(0) 52 | 53 | def _bytes_to_integer(self, integer_bytes): 54 | return struct.unpack(self.INTEGER_FORMAT, integer_bytes)[0] 55 | 56 | def _integer_to_bytes(self, integer): 57 | return struct.pack(self.INTEGER_FORMAT, integer) 58 | 59 | def _read_integer(self): 60 | return self._bytes_to_integer(self._f.read(self.INTEGER_LENGTH)) 61 | 62 | def _write_integer(self, integer): 63 | self.lock() 64 | self._f.write(self._integer_to_bytes(integer)) 65 | 66 | def write(self, data): 67 | self.lock() 68 | self._seek_end() 69 | object_address = self._f.tell() 70 | self._write_integer(len(data)) 71 | self._f.write(data) 72 | return object_address 73 | 74 | def read(self, address): 75 | self._f.seek(address) 76 | length = self._read_integer() 77 | data = self._f.read(length) 78 | return data 79 | 80 | def commit_root_address(self, root_address): 81 | self.lock() 82 | self._f.flush() 83 | self._seek_superblock() 84 | self._write_integer(root_address) 85 | self._f.flush() 86 | self.unlock() 87 | 88 | def get_root_address(self): 89 | self._seek_superblock() 90 | root_address = self._read_integer() 91 | return root_address 92 | 93 | def close(self): 94 | self.unlock() 95 | self._f.close() 96 | 97 | @property 98 | def closed(self): 99 | return self._f.closed 100 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/tests/__init__.py -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/tests/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/__pycache__/test_binary_tree.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/tests/__pycache__/test_binary_tree.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/__pycache__/test_integration.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/tests/__pycache__/test_integration.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/__pycache__/test_physical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/dbdb/tests/__pycache__/test_physical.cpython-36.pyc -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/test_binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import random 3 | 4 | from nose.tools import assert_raises, eq_ 5 | 6 | from dbdb.binary_tree import BinaryNode, BinaryTree, BinaryNodeRef, ValueRef 7 | 8 | 9 | class StubStorage(object): 10 | def __init__(self): 11 | self.d = [0] 12 | self.locked = False 13 | 14 | def lock(self): 15 | if not self.locked: 16 | self.locked = True 17 | return True 18 | else: 19 | return False 20 | 21 | def unlock(self): 22 | pass 23 | 24 | def get_root_address(self): 25 | return 0 26 | 27 | def write(self, string): 28 | address = len(self.d) 29 | self.d.append(string) 30 | return address 31 | 32 | def read(self, address): 33 | return self.d[address] 34 | 35 | 36 | class TestBinaryTree(object): 37 | def setup(self): 38 | self.tree = BinaryTree(StubStorage()) 39 | 40 | def test_get_missing_key_raises_key_error(self): 41 | with assert_raises(KeyError): 42 | self.tree.get('Not A Key In The Tree') 43 | 44 | def test_set_and_get_key(self): 45 | self.tree.set('a', 'b') 46 | eq_(self.tree.get('a'), 'b') 47 | 48 | def test_random_set_and_get_keys(self): 49 | ten_k = list(range(10000)) 50 | pairs = list(zip(random.sample(ten_k, 10), random.sample(ten_k, 10))) 51 | for i, (k, v) in enumerate(pairs, start=1): 52 | self.tree.set(k, v) 53 | eq_(len(self.tree), i) 54 | for k, v in pairs: 55 | eq_(self.tree.get(k), v) 56 | random.shuffle(pairs) 57 | for i, (k, v) in enumerate(pairs, start=1): 58 | self.tree.pop(k) 59 | eq_(len(self.tree), len(pairs) - i) 60 | 61 | def test_overwrite_and_get_key(self): 62 | self.tree.set('a', 'b') 63 | self.tree.set('a', 'c') 64 | eq_(self.tree.get('a'), 'c') 65 | 66 | def test_pop_non_existent_key(self): 67 | with assert_raises(KeyError): 68 | self.tree.pop('Not A Key In The Tree') 69 | 70 | def test_del_leaf_key(self): 71 | self.tree.set('b', '2') 72 | self.tree.pop('b') 73 | with assert_raises(KeyError): 74 | self.tree.get('b') 75 | 76 | def test_del_left_node_key(self): 77 | self.tree.set('b', '2') 78 | self.tree.set('a', '1') 79 | self.tree.pop('b') 80 | with assert_raises(KeyError): 81 | self.tree.get('b') 82 | self.tree.get('a') 83 | 84 | def test_del_right_node_key(self): 85 | self.tree.set('b', '2') 86 | self.tree.set('c', '3') 87 | self.tree.pop('b') 88 | with assert_raises(KeyError): 89 | self.tree.get('b') 90 | self.tree.get('c') 91 | 92 | def test_del_full_node_key(self): 93 | self.tree.set('b', '2') 94 | self.tree.set('a', '1') 95 | self.tree.set('c', '3') 96 | self.tree.pop('b') 97 | with assert_raises(KeyError): 98 | self.tree.get('b') 99 | self.tree.get('a') 100 | self.tree.get('c') 101 | 102 | 103 | class TestBinaryNodeRef(object): 104 | def test_to_string_leaf(self): 105 | n = BinaryNode(BinaryNodeRef(), 'k', ValueRef(address=999), BinaryNodeRef(), 1) 106 | pickled = BinaryNodeRef.referent_to_string(n) 107 | d = pickle.loads(pickled) 108 | eq_(d['left'], 0) 109 | eq_(d['key'], 'k') 110 | eq_(d['value'], 999) 111 | eq_(d['right'], 0) 112 | 113 | def test_to_string_nonleaf(self): 114 | left_ref = BinaryNodeRef(address=123) 115 | right_ref = BinaryNodeRef(address=321) 116 | n = BinaryNode(left_ref, 'k', ValueRef(address=999), right_ref, 3) 117 | pickled = BinaryNodeRef.referent_to_string(n) 118 | d = pickle.loads(pickled) 119 | eq_(d['left'], 123) 120 | eq_(d['key'], 'k') 121 | eq_(d['value'], 999) 122 | eq_(d['right'], 321) 123 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/test_integration.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | import shutil 4 | import subprocess 5 | import tempfile 6 | 7 | from nose.tools import assert_raises, eq_ 8 | 9 | import dbdb 10 | import dbdb.tool 11 | 12 | 13 | class TestDatabase(object): 14 | def setup(self): 15 | self.temp_dir = tempfile.mkdtemp() 16 | self.new_tempfile_name = os.path.join(self.temp_dir, 'new.db') 17 | self.tempfile_name = os.path.join(self.temp_dir, 'exisitng.db') 18 | open(self.tempfile_name, 'w').close() 19 | 20 | def teardown(self): 21 | shutil.rmtree(self.temp_dir, ignore_errors=True) 22 | 23 | def test_new_database_file(self): 24 | db = dbdb.connect(self.new_tempfile_name) 25 | db['a'] = 'aye' 26 | db.commit() 27 | db.close() 28 | 29 | def test_persistence(self): 30 | db = dbdb.connect(self.tempfile_name) 31 | db['b'] = 'bee' 32 | db['a'] = 'aye' 33 | db['c'] = 'see' 34 | db.commit() 35 | db['d'] = 'dee' 36 | eq_(len(db), 4) 37 | db.close() 38 | db = dbdb.connect(self.tempfile_name) 39 | eq_(db['a'], 'aye') 40 | eq_(db['b'], 'bee') 41 | eq_(db['c'], 'see') 42 | with assert_raises(KeyError): 43 | db['d'] 44 | eq_(len(db), 3) 45 | db.close() 46 | 47 | 48 | class TestTool(object): 49 | def setup(self): 50 | with tempfile.NamedTemporaryFile(delete=False) as temp_f: 51 | self.tempfile_name = temp_f.name 52 | 53 | def teardown(self): 54 | os.remove(self.tempfile_name) 55 | 56 | def _tool(self, *args): 57 | return subprocess.check_output( 58 | ['python', '-m', 'dbdb.tool', self.tempfile_name] + list(args), 59 | stderr=subprocess.STDOUT, 60 | ) 61 | 62 | def test_get_non_existent(self): 63 | self._tool('set', 'a', b'b') 64 | self._tool('delete', 'a') 65 | with assert_raises(subprocess.CalledProcessError) as raised: 66 | self._tool('get', 'a') 67 | eq_(raised.exception.returncode, dbdb.tool.BAD_KEY) 68 | 69 | def test_tool(self): 70 | expected = b'b' 71 | self._tool('set', 'a', expected) 72 | actual = self._tool('get', 'a') 73 | eq_(actual, expected) 74 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tests/test_physical.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | from nose.tools import eq_ 5 | 6 | from dbdb.physical import Storage 7 | 8 | 9 | class TestStorage(object): 10 | 11 | def setup(self): 12 | self.f = tempfile.NamedTemporaryFile() 13 | self.p = Storage(self.f) 14 | 15 | def _get_superblock_and_data(self, value): 16 | superblock = value[:Storage.SUPERBLOCK_SIZE] 17 | data = value[Storage.SUPERBLOCK_SIZE:] 18 | return superblock, data 19 | 20 | def _get_f_contents(self): 21 | self.f.flush() 22 | with open(self.f.name, 'rb') as f: 23 | return f.read() 24 | 25 | def test_init_ensures_superblock(self): 26 | EMPTY_SUPERBLOCK = (b'\x00' * Storage.SUPERBLOCK_SIZE) 27 | self.f.seek(0, os.SEEK_END) 28 | value = self._get_f_contents() 29 | eq_(value, EMPTY_SUPERBLOCK) 30 | 31 | def test_write(self): 32 | self.p.write(b'ABCDE') 33 | value = self._get_f_contents() 34 | superblock, data = self._get_superblock_and_data(value) 35 | eq_(data, b'\x00\x00\x00\x00\x00\x00\x00\x05ABCDE') 36 | 37 | def test_read(self): 38 | self.f.seek(Storage.SUPERBLOCK_SIZE) 39 | self.f.write(b'\x00\x00\x00\x00\x00\x00\x00\x0801234567') 40 | value = self.p.read(Storage.SUPERBLOCK_SIZE) 41 | eq_(value, b'01234567') 42 | 43 | def test_commit_root_address(self): 44 | self.p.commit_root_address(257) 45 | root_bytes = self._get_f_contents()[:8] 46 | eq_(root_bytes, b'\x00\x00\x00\x00\x00\x00\x01\x01') 47 | 48 | def test_get_root_address(self): 49 | self.f.seek(0) 50 | self.f.write(b'\x00\x00\x00\x00\x00\x00\x02\x02') 51 | root_address = self.p.get_root_address() 52 | eq_(root_address, 514) 53 | 54 | def test_workflow(self): 55 | a1 = self.p.write(b'one') 56 | a2 = self.p.write(b'two') 57 | self.p.commit_root_address(a2) 58 | a3 = self.p.write(b'three') 59 | eq_(self.p.get_root_address(), a2) 60 | a4 = self.p.write(b'four') 61 | self.p.commit_root_address(a4) 62 | eq_(self.p.read(a1), b'one') 63 | eq_(self.p.read(a2), b'two') 64 | eq_(self.p.read(a3), b'three') 65 | eq_(self.p.read(a4), b'four') 66 | eq_(self.p.get_root_address(), a4) 67 | -------------------------------------------------------------------------------- /python_demo/71/code/dbdb/tool.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | import dbdb 5 | 6 | 7 | OK = 0 8 | BAD_ARGS = 1 9 | BAD_VERB = 2 10 | BAD_KEY = 3 11 | 12 | 13 | def usage(): 14 | print("Usage:", file=sys.stderr) 15 | print("\tpython -m dbdb.tool DBNAME get KEY", file=sys.stderr) 16 | print("\tpython -m dbdb.tool DBNAME set KEY VALUE", file=sys.stderr) 17 | print("\tpython -m dbdb.tool DBNAME delete KEY", file=sys.stderr) 18 | 19 | 20 | def main(argv): 21 | if not (4 <= len(argv) <= 5): 22 | usage() 23 | return BAD_ARGS 24 | dbname, verb, key, value = (argv[1:] + [None])[:4] 25 | if verb not in {'get', 'set', 'delete'}: 26 | usage() 27 | return BAD_VERB 28 | db = dbdb.connect(dbname) 29 | try: 30 | if verb == 'get': 31 | sys.stdout.write(db[key]) 32 | elif verb == 'set': 33 | db[key] = value 34 | db.commit() 35 | else: 36 | del db[key] 37 | db.commit() 38 | except KeyError: 39 | print("Key not found", file=sys.stderr) 40 | return BAD_KEY 41 | return OK 42 | 43 | 44 | if __name__ == '__main__': 45 | sys.exit(main(sys.argv)) 46 | -------------------------------------------------------------------------------- /python_demo/71/code/example.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_demo/71/code/example.db -------------------------------------------------------------------------------- /python_demo/71/code/requirements.txt: -------------------------------------------------------------------------------- 1 | portalocker==0.4 2 | 3 | # For testing 4 | nose==1.3.0 5 | -------------------------------------------------------------------------------- /python_demo/71/code/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | 6 | setup( 7 | name='dbdb', 8 | version='0.1', 9 | description='DogBed DataBase', 10 | author='Taavi Burns', 11 | author_email='taavi.burns@points.com', 12 | url='https://github.com/aosabook/500lines/tree/master/data-store', 13 | packages=['dbdb'], 14 | ) 15 | -------------------------------------------------------------------------------- /python_demo/71/code/tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py27, py34, pypy 8 | 9 | [testenv] 10 | commands = nosetests 11 | deps = 12 | nose 13 | portalocker 14 | -------------------------------------------------------------------------------- /python_demo/README.MD: -------------------------------------------------------------------------------- 1 | 按章节分类的课上演示代码 2 | -------------------------------------------------------------------------------- /python_knowledge_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/python_knowledge_map.jpg -------------------------------------------------------------------------------- /setup_pycharm_win10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/setup_pycharm_win10.pdf -------------------------------------------------------------------------------- /std_lib.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/std_lib.pdf -------------------------------------------------------------------------------- /timegeekbang.com/.gitignore: -------------------------------------------------------------------------------- 1 | .tox 2 | *.egg-info 3 | chapter.html 4 | -------------------------------------------------------------------------------- /timegeekbang.com/chinese_zodiac.py: -------------------------------------------------------------------------------- 1 | # 记录生肖,根据年份来判断生肖 2 | 3 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 4 | 5 | # print (chinese_zodiac[0:4] ) 6 | 7 | # print (chinese_zodiac[-1]) 8 | 9 | year = 2018 10 | print (year % 12) 11 | 12 | print (chinese_zodiac[year % 12]) 13 | 14 | print ( '狗' not in chinese_zodiac ) 15 | 16 | print (chinese_zodiac + 'abcd') 17 | 18 | print (chinese_zodiac * 3 ) 19 | -------------------------------------------------------------------------------- /timegeekbang.com/chinese_zodiac_v2.py: -------------------------------------------------------------------------------- 1 | # 记录生肖,根据年份来判断生肖 2 | 3 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 4 | 5 | # year = int(input('请用户输入出生年份')) 6 | # 7 | # if(chinese_zodiac[year % 12]) == '狗': 8 | # print ('狗年运势。。。') 9 | # 10 | # for cz in chinese_zodiac: 11 | # print(cz) 12 | # 13 | # for i in range(1,13): 14 | # print(i) 15 | # 16 | # for year in range(2000,2019): 17 | # print('%s 年的生肖是 %s' %(year, chinese_zodiac[year % 12])) 18 | # import time 19 | num = 5 20 | while True: 21 | num = num + 1 22 | 23 | if num == 10: 24 | continue 25 | 26 | print(num) 27 | # time.sleep(1) 28 | -------------------------------------------------------------------------------- /timegeekbang.com/class_test.py: -------------------------------------------------------------------------------- 1 | # user1 = {'name':'tom','hp':100} 2 | # user2 = {'name':'jerry','hp':80} 3 | # 4 | # def print_role(rolename): 5 | # print('name is %s ,hp is %s' %(rolename['name'], rolename['hp']) ) 6 | # 7 | # print_role(user1) 8 | 9 | 10 | class Player(): #定义一个类 11 | def __init__(self, name, hp, occu): 12 | self.__name = name # 变量被称作属性 13 | self.hp = hp 14 | self.occu = occu 15 | def print_role(self): #定义一个方法 16 | print('%s: %s %s' %(self.__name,self.hp,self.occu)) 17 | 18 | def updateName(self,newname): 19 | self.name = newname 20 | 21 | 22 | 23 | class Monster(): 24 | '定义怪物类' 25 | def __init__(self,hp=100): 26 | self.hp = hp 27 | def run(self): 28 | print('移动到某个位置') 29 | 30 | def whoami(self): 31 | print('我是怪物父类') 32 | class Animals(Monster): 33 | '普通怪物' 34 | def __init__(self,hp=10): 35 | super().__init__(hp) 36 | 37 | 38 | class Boss(Monster): 39 | 'Boss类怪物' 40 | def __init__(self,hp=1000): 41 | super().__init__(hp) 42 | def whoami(self): 43 | print('我是怪物我怕谁') 44 | 45 | a1 = Monster(200) 46 | print(a1.hp) 47 | print(a1.run()) 48 | a2 = Animals(1) 49 | print(a2.hp) 50 | print(a2.run()) 51 | 52 | a3 = Boss(800) 53 | a3.whoami() 54 | 55 | print('a1的类型 %s' %type(a1)) 56 | print('a2的类型 %s' %type(a2)) 57 | print('a3的类型 %s' %type(a3)) 58 | 59 | print(isinstance(a2,Monster)) 60 | # 61 | # user1 = Player('tom',100,'war') #类的实例化 62 | # user2 = Player('jerry',90,'master') 63 | # user1.print_role() 64 | # user2.print_role() 65 | # 66 | # 67 | # user1.updateName('wilson') 68 | # user1.print_role() 69 | # user1.__name = ('aaa') 70 | # user1.print_role() -------------------------------------------------------------------------------- /timegeekbang.com/code/Makefile: -------------------------------------------------------------------------------- 1 | chapter.html: chapter.md 2 | pandoc -s -o chapter.html chapter.md 3 | 4 | clean: 5 | find . -name \*.pyc -delete 6 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dbdb.interface import DBDB 4 | 5 | 6 | __all__ = ['DBDB', 'connect'] 7 | 8 | 9 | def connect(dbname): 10 | try: 11 | f = open(dbname, 'r+b') 12 | except IOError: 13 | fd = os.open(dbname, os.O_RDWR | os.O_CREAT) 14 | f = os.fdopen(fd, 'r+b') 15 | return DBDB(f) 16 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | 3 | 4 | from dbdb.logical import LogicalBase, ValueRef 5 | 6 | 7 | class BinaryNode(object): 8 | @classmethod 9 | def from_node(cls, node, **kwargs): 10 | length = node.length 11 | if 'left_ref' in kwargs: 12 | length += kwargs['left_ref'].length - node.left_ref.length 13 | if 'right_ref' in kwargs: 14 | length += kwargs['right_ref'].length - node.right_ref.length 15 | 16 | return cls( 17 | left_ref=kwargs.get('left_ref', node.left_ref), 18 | key=kwargs.get('key', node.key), 19 | value_ref=kwargs.get('value_ref', node.value_ref), 20 | right_ref=kwargs.get('right_ref', node.right_ref), 21 | length=length, 22 | ) 23 | 24 | def __init__(self, left_ref, key, value_ref, right_ref, length): 25 | self.left_ref = left_ref 26 | self.key = key 27 | self.value_ref = value_ref 28 | self.right_ref = right_ref 29 | self.length = length 30 | 31 | def store_refs(self, storage): 32 | self.value_ref.store(storage) 33 | self.left_ref.store(storage) 34 | self.right_ref.store(storage) 35 | 36 | 37 | class BinaryNodeRef(ValueRef): 38 | def prepare_to_store(self, storage): 39 | if self._referent: 40 | self._referent.store_refs(storage) 41 | 42 | @property 43 | def length(self): 44 | if self._referent is None and self._address: 45 | raise RuntimeError('Asking for BinaryNodeRef length of unloaded node') 46 | if self._referent: 47 | return self._referent.length 48 | else: 49 | return 0 50 | 51 | @staticmethod 52 | def referent_to_string(referent): 53 | return pickle.dumps({ 54 | 'left': referent.left_ref.address, 55 | 'key': referent.key, 56 | 'value': referent.value_ref.address, 57 | 'right': referent.right_ref.address, 58 | 'length': referent.length, 59 | }) 60 | 61 | @staticmethod 62 | def string_to_referent(string): 63 | d = pickle.loads(string) 64 | return BinaryNode( 65 | BinaryNodeRef(address=d['left']), 66 | d['key'], 67 | ValueRef(address=d['value']), 68 | BinaryNodeRef(address=d['right']), 69 | d['length'], 70 | ) 71 | 72 | 73 | class BinaryTree(LogicalBase): 74 | node_ref_class = BinaryNodeRef 75 | 76 | def _get(self, node, key): 77 | while node is not None: 78 | if key < node.key: 79 | node = self._follow(node.left_ref) 80 | elif node.key < key: 81 | node = self._follow(node.right_ref) 82 | else: 83 | return self._follow(node.value_ref) 84 | raise KeyError 85 | 86 | def _insert(self, node, key, value_ref): 87 | if node is None: 88 | new_node = BinaryNode( 89 | self.node_ref_class(), key, value_ref, self.node_ref_class(), 1) 90 | elif key < node.key: 91 | new_node = BinaryNode.from_node( 92 | node, 93 | left_ref=self._insert( 94 | self._follow(node.left_ref), key, value_ref)) 95 | elif node.key < key: 96 | new_node = BinaryNode.from_node( 97 | node, 98 | right_ref=self._insert( 99 | self._follow(node.right_ref), key, value_ref)) 100 | else: 101 | new_node = BinaryNode.from_node(node, value_ref=value_ref) 102 | return self.node_ref_class(referent=new_node) 103 | 104 | def _delete(self, node, key): 105 | if node is None: 106 | raise KeyError 107 | elif key < node.key: 108 | new_node = BinaryNode.from_node( 109 | node, 110 | left_ref=self._delete( 111 | self._follow(node.left_ref), key)) 112 | elif node.key < key: 113 | new_node = BinaryNode.from_node( 114 | node, 115 | right_ref=self._delete( 116 | self._follow(node.right_ref), key)) 117 | else: 118 | left = self._follow(node.left_ref) 119 | right = self._follow(node.right_ref) 120 | if left and right: 121 | replacement = self._find_max(left) 122 | left_ref = self._delete( 123 | self._follow(node.left_ref), replacement.key) 124 | new_node = BinaryNode( 125 | left_ref, 126 | replacement.key, 127 | replacement.value_ref, 128 | node.right_ref, 129 | left_ref.length + node.right_ref.length + 1, 130 | ) 131 | elif left: 132 | return node.left_ref 133 | else: 134 | return node.right_ref 135 | return self.node_ref_class(referent=new_node) 136 | 137 | def _find_max(self, node): 138 | while True: 139 | next_node = self._follow(node.right_ref) 140 | if next_node is None: 141 | return node 142 | node = next_node 143 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/interface.py: -------------------------------------------------------------------------------- 1 | from dbdb.binary_tree import BinaryTree 2 | from dbdb.physical import Storage 3 | 4 | 5 | class DBDB(object): 6 | 7 | def __init__(self, f): 8 | self._storage = Storage(f) 9 | self._tree = BinaryTree(self._storage) 10 | 11 | def _assert_not_closed(self): 12 | if self._storage.closed: 13 | raise ValueError('Database closed.') 14 | 15 | def close(self): 16 | self._storage.close() 17 | 18 | def commit(self): 19 | self._assert_not_closed() 20 | self._tree.commit() 21 | 22 | def __getitem__(self, key): 23 | self._assert_not_closed() 24 | return self._tree.get(key) 25 | 26 | def __setitem__(self, key, value): 27 | self._assert_not_closed() 28 | return self._tree.set(key, value) 29 | 30 | def __delitem__(self, key): 31 | self._assert_not_closed() 32 | return self._tree.pop(key) 33 | 34 | def __contains__(self, key): 35 | try: 36 | self[key] 37 | except KeyError: 38 | return False 39 | else: 40 | return True 41 | 42 | def __len__(self): 43 | return len(self._tree) 44 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/logical.py: -------------------------------------------------------------------------------- 1 | class ValueRef(object): 2 | def prepare_to_store(self, storage): 3 | pass 4 | 5 | @staticmethod 6 | def referent_to_string(referent): 7 | return referent.encode('utf-8') 8 | 9 | @staticmethod 10 | def string_to_referent(string): 11 | return string.decode('utf-8') 12 | 13 | def __init__(self, referent=None, address=0): 14 | self._referent = referent 15 | self._address = address 16 | 17 | @property 18 | def address(self): 19 | return self._address 20 | 21 | def get(self, storage): 22 | if self._referent is None and self._address: 23 | self._referent = self.string_to_referent(storage.read(self._address)) 24 | return self._referent 25 | 26 | def store(self, storage): 27 | if self._referent is not None and not self._address: 28 | self.prepare_to_store(storage) 29 | self._address = storage.write(self.referent_to_string(self._referent)) 30 | 31 | 32 | class LogicalBase(object): 33 | node_ref_class = None 34 | value_ref_class = ValueRef 35 | 36 | def __init__(self, storage): 37 | self._storage = storage 38 | self._refresh_tree_ref() 39 | 40 | def commit(self): 41 | self._tree_ref.store(self._storage) 42 | self._storage.commit_root_address(self._tree_ref.address) 43 | 44 | def _refresh_tree_ref(self): 45 | self._tree_ref = self.node_ref_class( 46 | address=self._storage.get_root_address()) 47 | 48 | def get(self, key): 49 | if not self._storage.locked: 50 | self._refresh_tree_ref() 51 | return self._get(self._follow(self._tree_ref), key) 52 | 53 | def set(self, key, value): 54 | if self._storage.lock(): 55 | self._refresh_tree_ref() 56 | self._tree_ref = self._insert( 57 | self._follow(self._tree_ref), key, self.value_ref_class(value)) 58 | 59 | def pop(self, key): 60 | if self._storage.lock(): 61 | self._refresh_tree_ref() 62 | self._tree_ref = self._delete( 63 | self._follow(self._tree_ref), key) 64 | 65 | def _follow(self, ref): 66 | return ref.get(self._storage) 67 | 68 | def __len__(self): 69 | if not self._storage.locked: 70 | self._refresh_tree_ref() 71 | root = self._follow(self._tree_ref) 72 | if root: 73 | return root.length 74 | else: 75 | return 0 76 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/physical.py: -------------------------------------------------------------------------------- 1 | # This started as a very thin wrapper around a file object, with intent to 2 | # provide an object address on write() and a superblock. But as I was writing 3 | # it, I realised that the user really wouldn't want to deal with the lengths of 4 | # the writen chunks (and Pickle won't do it for you), so this module would have 5 | # to abstract the file object into it's own degenerate key/value store. 6 | # (Degenerate because you can't pick the keys, and it never releases storage, 7 | # even when it becomes unreachable!) 8 | 9 | import os 10 | import struct 11 | 12 | import portalocker 13 | 14 | 15 | class Storage(object): 16 | SUPERBLOCK_SIZE = 4096 17 | INTEGER_FORMAT = "!Q" 18 | INTEGER_LENGTH = 8 19 | 20 | def __init__(self, f): 21 | self._f = f 22 | self.locked = False 23 | self._ensure_superblock() 24 | 25 | def _ensure_superblock(self): 26 | self.lock() 27 | self._seek_end() 28 | end_address = self._f.tell() 29 | if end_address < self.SUPERBLOCK_SIZE: 30 | self._f.write(b'\x00' * (self.SUPERBLOCK_SIZE - end_address)) 31 | self.unlock() 32 | 33 | def lock(self): 34 | if not self.locked: 35 | portalocker.lock(self._f, portalocker.LOCK_EX) 36 | self.locked = True 37 | return True 38 | else: 39 | return False 40 | 41 | def unlock(self): 42 | if self.locked: 43 | self._f.flush() 44 | portalocker.unlock(self._f) 45 | self.locked = False 46 | 47 | def _seek_end(self): 48 | self._f.seek(0, os.SEEK_END) 49 | 50 | def _seek_superblock(self): 51 | self._f.seek(0) 52 | 53 | def _bytes_to_integer(self, integer_bytes): 54 | return struct.unpack(self.INTEGER_FORMAT, integer_bytes)[0] 55 | 56 | def _integer_to_bytes(self, integer): 57 | return struct.pack(self.INTEGER_FORMAT, integer) 58 | 59 | def _read_integer(self): 60 | return self._bytes_to_integer(self._f.read(self.INTEGER_LENGTH)) 61 | 62 | def _write_integer(self, integer): 63 | self.lock() 64 | self._f.write(self._integer_to_bytes(integer)) 65 | 66 | def write(self, data): 67 | self.lock() 68 | self._seek_end() 69 | object_address = self._f.tell() 70 | self._write_integer(len(data)) 71 | self._f.write(data) 72 | return object_address 73 | 74 | def read(self, address): 75 | self._f.seek(address) 76 | length = self._read_integer() 77 | data = self._f.read(length) 78 | return data 79 | 80 | def commit_root_address(self, root_address): 81 | self.lock() 82 | self._f.flush() 83 | self._seek_superblock() 84 | self._write_integer(root_address) 85 | self._f.flush() 86 | self.unlock() 87 | 88 | def get_root_address(self): 89 | self._seek_superblock() 90 | root_address = self._read_integer() 91 | return root_address 92 | 93 | def close(self): 94 | self.unlock() 95 | self._f.close() 96 | 97 | @property 98 | def closed(self): 99 | return self._f.closed 100 | -------------------------------------------------------------------------------- /timegeekbang.com/code/build/lib/dbdb/tool.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | import dbdb 5 | 6 | 7 | OK = 0 8 | BAD_ARGS = 1 9 | BAD_VERB = 2 10 | BAD_KEY = 3 11 | 12 | 13 | def usage(): 14 | print("Usage:", file=sys.stderr) 15 | print("\tpython -m dbdb.tool DBNAME get KEY", file=sys.stderr) 16 | print("\tpython -m dbdb.tool DBNAME set KEY VALUE", file=sys.stderr) 17 | print("\tpython -m dbdb.tool DBNAME delete KEY", file=sys.stderr) 18 | 19 | 20 | def main(argv): 21 | if not (4 <= len(argv) <= 5): 22 | usage() 23 | return BAD_ARGS 24 | dbname, verb, key, value = (argv[1:] + [None])[:4] 25 | if verb not in {'get', 'set', 'delete'}: 26 | usage() 27 | return BAD_VERB 28 | db = dbdb.connect(dbname) 29 | try: 30 | if verb == 'get': 31 | sys.stdout.write(db[key]) 32 | elif verb == 'set': 33 | db[key] = value 34 | db.commit() 35 | else: 36 | del db[key] 37 | db.commit() 38 | except KeyError: 39 | print("Key not found", file=sys.stderr) 40 | return BAD_KEY 41 | return OK 42 | 43 | 44 | if __name__ == '__main__': 45 | sys.exit(main(sys.argv)) 46 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dbdb.interface import DBDB 4 | 5 | 6 | __all__ = ['DBDB', 'connect'] 7 | 8 | 9 | def connect(dbname): 10 | try: 11 | f = open(dbname, 'r+b') 12 | except IOError: 13 | fd = os.open(dbname, os.O_RDWR | os.O_CREAT) 14 | f = os.fdopen(fd, 'r+b') 15 | return DBDB(f) 16 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/binary_tree.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/binary_tree.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/interface.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/interface.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/logical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/logical.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/physical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/physical.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/__pycache__/tool.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/__pycache__/tool.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | 3 | 4 | from dbdb.logical import LogicalBase, ValueRef 5 | 6 | 7 | class BinaryNode(object): 8 | @classmethod 9 | def from_node(cls, node, **kwargs): 10 | length = node.length 11 | if 'left_ref' in kwargs: 12 | length += kwargs['left_ref'].length - node.left_ref.length 13 | if 'right_ref' in kwargs: 14 | length += kwargs['right_ref'].length - node.right_ref.length 15 | 16 | return cls( 17 | left_ref=kwargs.get('left_ref', node.left_ref), 18 | key=kwargs.get('key', node.key), 19 | value_ref=kwargs.get('value_ref', node.value_ref), 20 | right_ref=kwargs.get('right_ref', node.right_ref), 21 | length=length, 22 | ) 23 | 24 | def __init__(self, left_ref, key, value_ref, right_ref, length): 25 | self.left_ref = left_ref 26 | self.key = key 27 | self.value_ref = value_ref 28 | self.right_ref = right_ref 29 | self.length = length 30 | 31 | def store_refs(self, storage): 32 | self.value_ref.store(storage) 33 | self.left_ref.store(storage) 34 | self.right_ref.store(storage) 35 | 36 | 37 | class BinaryNodeRef(ValueRef): 38 | def prepare_to_store(self, storage): 39 | if self._referent: 40 | self._referent.store_refs(storage) 41 | 42 | @property 43 | def length(self): 44 | if self._referent is None and self._address: 45 | raise RuntimeError('Asking for BinaryNodeRef length of unloaded node') 46 | if self._referent: 47 | return self._referent.length 48 | else: 49 | return 0 50 | 51 | @staticmethod 52 | def referent_to_string(referent): 53 | return pickle.dumps({ 54 | 'left': referent.left_ref.address, 55 | 'key': referent.key, 56 | 'value': referent.value_ref.address, 57 | 'right': referent.right_ref.address, 58 | 'length': referent.length, 59 | }) 60 | 61 | @staticmethod 62 | def string_to_referent(string): 63 | d = pickle.loads(string) 64 | return BinaryNode( 65 | BinaryNodeRef(address=d['left']), 66 | d['key'], 67 | ValueRef(address=d['value']), 68 | BinaryNodeRef(address=d['right']), 69 | d['length'], 70 | ) 71 | 72 | 73 | class BinaryTree(LogicalBase): 74 | node_ref_class = BinaryNodeRef 75 | 76 | def _get(self, node, key): 77 | while node is not None: 78 | if key < node.key: 79 | node = self._follow(node.left_ref) 80 | elif node.key < key: 81 | node = self._follow(node.right_ref) 82 | else: 83 | return self._follow(node.value_ref) 84 | raise KeyError 85 | 86 | def _insert(self, node, key, value_ref): 87 | if node is None: 88 | new_node = BinaryNode( 89 | self.node_ref_class(), key, value_ref, self.node_ref_class(), 1) 90 | elif key < node.key: 91 | new_node = BinaryNode.from_node( 92 | node, 93 | left_ref=self._insert( 94 | self._follow(node.left_ref), key, value_ref)) 95 | elif node.key < key: 96 | new_node = BinaryNode.from_node( 97 | node, 98 | right_ref=self._insert( 99 | self._follow(node.right_ref), key, value_ref)) 100 | else: 101 | new_node = BinaryNode.from_node(node, value_ref=value_ref) 102 | return self.node_ref_class(referent=new_node) 103 | 104 | def _delete(self, node, key): 105 | if node is None: 106 | raise KeyError 107 | elif key < node.key: 108 | new_node = BinaryNode.from_node( 109 | node, 110 | left_ref=self._delete( 111 | self._follow(node.left_ref), key)) 112 | elif node.key < key: 113 | new_node = BinaryNode.from_node( 114 | node, 115 | right_ref=self._delete( 116 | self._follow(node.right_ref), key)) 117 | else: 118 | left = self._follow(node.left_ref) 119 | right = self._follow(node.right_ref) 120 | if left and right: 121 | replacement = self._find_max(left) 122 | left_ref = self._delete( 123 | self._follow(node.left_ref), replacement.key) 124 | new_node = BinaryNode( 125 | left_ref, 126 | replacement.key, 127 | replacement.value_ref, 128 | node.right_ref, 129 | left_ref.length + node.right_ref.length + 1, 130 | ) 131 | elif left: 132 | return node.left_ref 133 | else: 134 | return node.right_ref 135 | return self.node_ref_class(referent=new_node) 136 | 137 | def _find_max(self, node): 138 | while True: 139 | next_node = self._follow(node.right_ref) 140 | if next_node is None: 141 | return node 142 | node = next_node 143 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/interface.py: -------------------------------------------------------------------------------- 1 | from dbdb.binary_tree import BinaryTree 2 | from dbdb.physical import Storage 3 | 4 | 5 | class DBDB(object): 6 | 7 | def __init__(self, f): 8 | self._storage = Storage(f) 9 | self._tree = BinaryTree(self._storage) 10 | 11 | def _assert_not_closed(self): 12 | if self._storage.closed: 13 | raise ValueError('Database closed.') 14 | 15 | def close(self): 16 | self._storage.close() 17 | 18 | def commit(self): 19 | self._assert_not_closed() 20 | self._tree.commit() 21 | 22 | def __getitem__(self, key): 23 | self._assert_not_closed() 24 | return self._tree.get(key) 25 | 26 | def __setitem__(self, key, value): 27 | self._assert_not_closed() 28 | return self._tree.set(key, value) 29 | 30 | def __delitem__(self, key): 31 | self._assert_not_closed() 32 | return self._tree.pop(key) 33 | 34 | def __contains__(self, key): 35 | try: 36 | self[key] 37 | except KeyError: 38 | return False 39 | else: 40 | return True 41 | 42 | def __len__(self): 43 | return len(self._tree) 44 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/logical.py: -------------------------------------------------------------------------------- 1 | class ValueRef(object): 2 | def prepare_to_store(self, storage): 3 | pass 4 | 5 | @staticmethod 6 | def referent_to_string(referent): 7 | return referent.encode('utf-8') 8 | 9 | @staticmethod 10 | def string_to_referent(string): 11 | return string.decode('utf-8') 12 | 13 | def __init__(self, referent=None, address=0): 14 | self._referent = referent 15 | self._address = address 16 | 17 | @property 18 | def address(self): 19 | return self._address 20 | 21 | def get(self, storage): 22 | if self._referent is None and self._address: 23 | self._referent = self.string_to_referent(storage.read(self._address)) 24 | return self._referent 25 | 26 | def store(self, storage): 27 | if self._referent is not None and not self._address: 28 | self.prepare_to_store(storage) 29 | self._address = storage.write(self.referent_to_string(self._referent)) 30 | 31 | 32 | class LogicalBase(object): 33 | node_ref_class = None 34 | value_ref_class = ValueRef 35 | 36 | def __init__(self, storage): 37 | self._storage = storage 38 | self._refresh_tree_ref() 39 | 40 | def commit(self): 41 | self._tree_ref.store(self._storage) 42 | self._storage.commit_root_address(self._tree_ref.address) 43 | 44 | def _refresh_tree_ref(self): 45 | self._tree_ref = self.node_ref_class( 46 | address=self._storage.get_root_address()) 47 | 48 | def get(self, key): 49 | if not self._storage.locked: 50 | self._refresh_tree_ref() 51 | return self._get(self._follow(self._tree_ref), key) 52 | 53 | def set(self, key, value): 54 | if self._storage.lock(): 55 | self._refresh_tree_ref() 56 | self._tree_ref = self._insert( 57 | self._follow(self._tree_ref), key, self.value_ref_class(value)) 58 | 59 | def pop(self, key): 60 | if self._storage.lock(): 61 | self._refresh_tree_ref() 62 | self._tree_ref = self._delete( 63 | self._follow(self._tree_ref), key) 64 | 65 | def _follow(self, ref): 66 | return ref.get(self._storage) 67 | 68 | def __len__(self): 69 | if not self._storage.locked: 70 | self._refresh_tree_ref() 71 | root = self._follow(self._tree_ref) 72 | if root: 73 | return root.length 74 | else: 75 | return 0 76 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/physical.py: -------------------------------------------------------------------------------- 1 | # This started as a very thin wrapper around a file object, with intent to 2 | # provide an object address on write() and a superblock. But as I was writing 3 | # it, I realised that the user really wouldn't want to deal with the lengths of 4 | # the writen chunks (and Pickle won't do it for you), so this module would have 5 | # to abstract the file object into it's own degenerate key/value store. 6 | # (Degenerate because you can't pick the keys, and it never releases storage, 7 | # even when it becomes unreachable!) 8 | 9 | import os 10 | import struct 11 | 12 | import portalocker 13 | 14 | 15 | class Storage(object): 16 | SUPERBLOCK_SIZE = 4096 17 | INTEGER_FORMAT = "!Q" 18 | INTEGER_LENGTH = 8 19 | 20 | def __init__(self, f): 21 | self._f = f 22 | self.locked = False 23 | self._ensure_superblock() 24 | 25 | def _ensure_superblock(self): 26 | self.lock() 27 | self._seek_end() 28 | end_address = self._f.tell() 29 | if end_address < self.SUPERBLOCK_SIZE: 30 | self._f.write(b'\x00' * (self.SUPERBLOCK_SIZE - end_address)) 31 | self.unlock() 32 | 33 | def lock(self): 34 | if not self.locked: 35 | portalocker.lock(self._f, portalocker.LOCK_EX) 36 | self.locked = True 37 | return True 38 | else: 39 | return False 40 | 41 | def unlock(self): 42 | if self.locked: 43 | self._f.flush() 44 | portalocker.unlock(self._f) 45 | self.locked = False 46 | 47 | def _seek_end(self): 48 | self._f.seek(0, os.SEEK_END) 49 | 50 | def _seek_superblock(self): 51 | self._f.seek(0) 52 | 53 | def _bytes_to_integer(self, integer_bytes): 54 | return struct.unpack(self.INTEGER_FORMAT, integer_bytes)[0] 55 | 56 | def _integer_to_bytes(self, integer): 57 | return struct.pack(self.INTEGER_FORMAT, integer) 58 | 59 | def _read_integer(self): 60 | return self._bytes_to_integer(self._f.read(self.INTEGER_LENGTH)) 61 | 62 | def _write_integer(self, integer): 63 | self.lock() 64 | self._f.write(self._integer_to_bytes(integer)) 65 | 66 | def write(self, data): 67 | self.lock() 68 | self._seek_end() 69 | object_address = self._f.tell() 70 | self._write_integer(len(data)) 71 | self._f.write(data) 72 | return object_address 73 | 74 | def read(self, address): 75 | self._f.seek(address) 76 | length = self._read_integer() 77 | data = self._f.read(length) 78 | return data 79 | 80 | def commit_root_address(self, root_address): 81 | self.lock() 82 | self._f.flush() 83 | self._seek_superblock() 84 | self._write_integer(root_address) 85 | self._f.flush() 86 | self.unlock() 87 | 88 | def get_root_address(self): 89 | self._seek_superblock() 90 | root_address = self._read_integer() 91 | return root_address 92 | 93 | def close(self): 94 | self.unlock() 95 | self._f.close() 96 | 97 | @property 98 | def closed(self): 99 | return self._f.closed 100 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/tests/__init__.py -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/tests/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/__pycache__/test_binary_tree.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/tests/__pycache__/test_binary_tree.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/__pycache__/test_integration.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/tests/__pycache__/test_integration.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/__pycache__/test_physical.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/dbdb/tests/__pycache__/test_physical.cpython-36.pyc -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/test_binary_tree.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import random 3 | 4 | from nose.tools import assert_raises, eq_ 5 | 6 | from dbdb.binary_tree import BinaryNode, BinaryTree, BinaryNodeRef, ValueRef 7 | 8 | 9 | class StubStorage(object): 10 | def __init__(self): 11 | self.d = [0] 12 | self.locked = False 13 | 14 | def lock(self): 15 | if not self.locked: 16 | self.locked = True 17 | return True 18 | else: 19 | return False 20 | 21 | def unlock(self): 22 | pass 23 | 24 | def get_root_address(self): 25 | return 0 26 | 27 | def write(self, string): 28 | address = len(self.d) 29 | self.d.append(string) 30 | return address 31 | 32 | def read(self, address): 33 | return self.d[address] 34 | 35 | 36 | class TestBinaryTree(object): 37 | def setup(self): 38 | self.tree = BinaryTree(StubStorage()) 39 | 40 | def test_get_missing_key_raises_key_error(self): 41 | with assert_raises(KeyError): 42 | self.tree.get('Not A Key In The Tree') 43 | 44 | def test_set_and_get_key(self): 45 | self.tree.set('a', 'b') 46 | eq_(self.tree.get('a'), 'b') 47 | 48 | def test_random_set_and_get_keys(self): 49 | ten_k = list(range(10000)) 50 | pairs = list(zip(random.sample(ten_k, 10), random.sample(ten_k, 10))) 51 | for i, (k, v) in enumerate(pairs, start=1): 52 | self.tree.set(k, v) 53 | eq_(len(self.tree), i) 54 | for k, v in pairs: 55 | eq_(self.tree.get(k), v) 56 | random.shuffle(pairs) 57 | for i, (k, v) in enumerate(pairs, start=1): 58 | self.tree.pop(k) 59 | eq_(len(self.tree), len(pairs) - i) 60 | 61 | def test_overwrite_and_get_key(self): 62 | self.tree.set('a', 'b') 63 | self.tree.set('a', 'c') 64 | eq_(self.tree.get('a'), 'c') 65 | 66 | def test_pop_non_existent_key(self): 67 | with assert_raises(KeyError): 68 | self.tree.pop('Not A Key In The Tree') 69 | 70 | def test_del_leaf_key(self): 71 | self.tree.set('b', '2') 72 | self.tree.pop('b') 73 | with assert_raises(KeyError): 74 | self.tree.get('b') 75 | 76 | def test_del_left_node_key(self): 77 | self.tree.set('b', '2') 78 | self.tree.set('a', '1') 79 | self.tree.pop('b') 80 | with assert_raises(KeyError): 81 | self.tree.get('b') 82 | self.tree.get('a') 83 | 84 | def test_del_right_node_key(self): 85 | self.tree.set('b', '2') 86 | self.tree.set('c', '3') 87 | self.tree.pop('b') 88 | with assert_raises(KeyError): 89 | self.tree.get('b') 90 | self.tree.get('c') 91 | 92 | def test_del_full_node_key(self): 93 | self.tree.set('b', '2') 94 | self.tree.set('a', '1') 95 | self.tree.set('c', '3') 96 | self.tree.pop('b') 97 | with assert_raises(KeyError): 98 | self.tree.get('b') 99 | self.tree.get('a') 100 | self.tree.get('c') 101 | 102 | 103 | class TestBinaryNodeRef(object): 104 | def test_to_string_leaf(self): 105 | n = BinaryNode(BinaryNodeRef(), 'k', ValueRef(address=999), BinaryNodeRef(), 1) 106 | pickled = BinaryNodeRef.referent_to_string(n) 107 | d = pickle.loads(pickled) 108 | eq_(d['left'], 0) 109 | eq_(d['key'], 'k') 110 | eq_(d['value'], 999) 111 | eq_(d['right'], 0) 112 | 113 | def test_to_string_nonleaf(self): 114 | left_ref = BinaryNodeRef(address=123) 115 | right_ref = BinaryNodeRef(address=321) 116 | n = BinaryNode(left_ref, 'k', ValueRef(address=999), right_ref, 3) 117 | pickled = BinaryNodeRef.referent_to_string(n) 118 | d = pickle.loads(pickled) 119 | eq_(d['left'], 123) 120 | eq_(d['key'], 'k') 121 | eq_(d['value'], 999) 122 | eq_(d['right'], 321) 123 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/test_integration.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | import shutil 4 | import subprocess 5 | import tempfile 6 | 7 | from nose.tools import assert_raises, eq_ 8 | 9 | import dbdb 10 | import dbdb.tool 11 | 12 | 13 | class TestDatabase(object): 14 | def setup(self): 15 | self.temp_dir = tempfile.mkdtemp() 16 | self.new_tempfile_name = os.path.join(self.temp_dir, 'new.db') 17 | self.tempfile_name = os.path.join(self.temp_dir, 'exisitng.db') 18 | open(self.tempfile_name, 'w').close() 19 | 20 | def teardown(self): 21 | shutil.rmtree(self.temp_dir, ignore_errors=True) 22 | 23 | def test_new_database_file(self): 24 | db = dbdb.connect(self.new_tempfile_name) 25 | db['a'] = 'aye' 26 | db.commit() 27 | db.close() 28 | 29 | def test_persistence(self): 30 | db = dbdb.connect(self.tempfile_name) 31 | db['b'] = 'bee' 32 | db['a'] = 'aye' 33 | db['c'] = 'see' 34 | db.commit() 35 | db['d'] = 'dee' 36 | eq_(len(db), 4) 37 | db.close() 38 | db = dbdb.connect(self.tempfile_name) 39 | eq_(db['a'], 'aye') 40 | eq_(db['b'], 'bee') 41 | eq_(db['c'], 'see') 42 | with assert_raises(KeyError): 43 | db['d'] 44 | eq_(len(db), 3) 45 | db.close() 46 | 47 | 48 | class TestTool(object): 49 | def setup(self): 50 | with tempfile.NamedTemporaryFile(delete=False) as temp_f: 51 | self.tempfile_name = temp_f.name 52 | 53 | def teardown(self): 54 | os.remove(self.tempfile_name) 55 | 56 | def _tool(self, *args): 57 | return subprocess.check_output( 58 | ['python', '-m', 'dbdb.tool', self.tempfile_name] + list(args), 59 | stderr=subprocess.STDOUT, 60 | ) 61 | 62 | def test_get_non_existent(self): 63 | self._tool('set', 'a', b'b') 64 | self._tool('delete', 'a') 65 | with assert_raises(subprocess.CalledProcessError) as raised: 66 | self._tool('get', 'a') 67 | eq_(raised.exception.returncode, dbdb.tool.BAD_KEY) 68 | 69 | def test_tool(self): 70 | expected = b'b' 71 | self._tool('set', 'a', expected) 72 | actual = self._tool('get', 'a') 73 | eq_(actual, expected) 74 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tests/test_physical.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | from nose.tools import eq_ 5 | 6 | from dbdb.physical import Storage 7 | 8 | 9 | class TestStorage(object): 10 | 11 | def setup(self): 12 | self.f = tempfile.NamedTemporaryFile() 13 | self.p = Storage(self.f) 14 | 15 | def _get_superblock_and_data(self, value): 16 | superblock = value[:Storage.SUPERBLOCK_SIZE] 17 | data = value[Storage.SUPERBLOCK_SIZE:] 18 | return superblock, data 19 | 20 | def _get_f_contents(self): 21 | self.f.flush() 22 | with open(self.f.name, 'rb') as f: 23 | return f.read() 24 | 25 | def test_init_ensures_superblock(self): 26 | EMPTY_SUPERBLOCK = (b'\x00' * Storage.SUPERBLOCK_SIZE) 27 | self.f.seek(0, os.SEEK_END) 28 | value = self._get_f_contents() 29 | eq_(value, EMPTY_SUPERBLOCK) 30 | 31 | def test_write(self): 32 | self.p.write(b'ABCDE') 33 | value = self._get_f_contents() 34 | superblock, data = self._get_superblock_and_data(value) 35 | eq_(data, b'\x00\x00\x00\x00\x00\x00\x00\x05ABCDE') 36 | 37 | def test_read(self): 38 | self.f.seek(Storage.SUPERBLOCK_SIZE) 39 | self.f.write(b'\x00\x00\x00\x00\x00\x00\x00\x0801234567') 40 | value = self.p.read(Storage.SUPERBLOCK_SIZE) 41 | eq_(value, b'01234567') 42 | 43 | def test_commit_root_address(self): 44 | self.p.commit_root_address(257) 45 | root_bytes = self._get_f_contents()[:8] 46 | eq_(root_bytes, b'\x00\x00\x00\x00\x00\x00\x01\x01') 47 | 48 | def test_get_root_address(self): 49 | self.f.seek(0) 50 | self.f.write(b'\x00\x00\x00\x00\x00\x00\x02\x02') 51 | root_address = self.p.get_root_address() 52 | eq_(root_address, 514) 53 | 54 | def test_workflow(self): 55 | a1 = self.p.write(b'one') 56 | a2 = self.p.write(b'two') 57 | self.p.commit_root_address(a2) 58 | a3 = self.p.write(b'three') 59 | eq_(self.p.get_root_address(), a2) 60 | a4 = self.p.write(b'four') 61 | self.p.commit_root_address(a4) 62 | eq_(self.p.read(a1), b'one') 63 | eq_(self.p.read(a2), b'two') 64 | eq_(self.p.read(a3), b'three') 65 | eq_(self.p.read(a4), b'four') 66 | eq_(self.p.get_root_address(), a4) 67 | -------------------------------------------------------------------------------- /timegeekbang.com/code/dbdb/tool.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import sys 3 | 4 | import dbdb 5 | 6 | 7 | OK = 0 8 | BAD_ARGS = 1 9 | BAD_VERB = 2 10 | BAD_KEY = 3 11 | 12 | 13 | def usage(): 14 | print("Usage:", file=sys.stderr) 15 | print("\tpython -m dbdb.tool DBNAME get KEY", file=sys.stderr) 16 | print("\tpython -m dbdb.tool DBNAME set KEY VALUE", file=sys.stderr) 17 | print("\tpython -m dbdb.tool DBNAME delete KEY", file=sys.stderr) 18 | 19 | 20 | def main(argv): 21 | if not (4 <= len(argv) <= 5): 22 | usage() 23 | return BAD_ARGS 24 | dbname, verb, key, value = (argv[1:] + [None])[:4] 25 | if verb not in {'get', 'set', 'delete'}: 26 | usage() 27 | return BAD_VERB 28 | db = dbdb.connect(dbname) 29 | try: 30 | if verb == 'get': 31 | sys.stdout.write(db[key]) 32 | elif verb == 'set': 33 | db[key] = value 34 | db.commit() 35 | else: 36 | del db[key] 37 | db.commit() 38 | except KeyError: 39 | print("Key not found", file=sys.stderr) 40 | return BAD_KEY 41 | return OK 42 | 43 | 44 | if __name__ == '__main__': 45 | sys.exit(main(sys.argv)) 46 | -------------------------------------------------------------------------------- /timegeekbang.com/code/example.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/code/example.db -------------------------------------------------------------------------------- /timegeekbang.com/code/requirements.txt: -------------------------------------------------------------------------------- 1 | portalocker==0.4 2 | 3 | # For testing 4 | nose==1.3.0 5 | -------------------------------------------------------------------------------- /timegeekbang.com/code/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | 6 | setup( 7 | name='dbdb', 8 | version='0.1', 9 | description='DogBed DataBase', 10 | author='Taavi Burns', 11 | author_email='taavi.burns@points.com', 12 | url='https://github.com/aosabook/500lines/tree/master/data-store', 13 | packages=['dbdb'], 14 | ) 15 | -------------------------------------------------------------------------------- /timegeekbang.com/code/tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py27, py34, pypy 8 | 9 | [testenv] 10 | commands = nosetests 11 | deps = 12 | nose 13 | portalocker 14 | -------------------------------------------------------------------------------- /timegeekbang.com/con_cus.py: -------------------------------------------------------------------------------- 1 | from threading import Thread,current_thread 2 | import time 3 | import random 4 | from queue import Queue 5 | 6 | queue = Queue(5) 7 | 8 | class ProducerThread(Thread): 9 | def run(self): 10 | name = current_thread().getName() 11 | nums = range(100) 12 | global queue 13 | while True: 14 | num = random.choice(nums) 15 | queue.put(num) 16 | print('生产者 %s 生产了数据 %s' %(name, num)) 17 | t = random.randint(1,3) 18 | time.sleep(t) 19 | print('生产者 %s 睡眠了 %s 秒' %(name, t)) 20 | 21 | class ConsumerTheard(Thread): 22 | def run(self): 23 | name = current_thread().getName() 24 | global queue 25 | while True: 26 | num = queue.get() 27 | queue.task_done() 28 | print('消费者 %s 消耗了数据 %s' %(name, num)) 29 | t = random.randint(1,5) 30 | time.sleep(t) 31 | print('消费者 %s 睡眠了 %s 秒' % (name, t)) 32 | 33 | 34 | p1 = ProducerThread(name = 'p1') 35 | p1.start() 36 | p2 = ProducerThread(name = 'p2') 37 | p2.start() 38 | p3 = ProducerThread(name = 'p3') 39 | p3.start() 40 | c1 = ConsumerTheard(name = 'c1') 41 | c1.start() 42 | c2 = ConsumerTheard(name = 'c2') 43 | c2.start() -------------------------------------------------------------------------------- /timegeekbang.com/dir_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | print( os.path.abspath('..')) 3 | print( os.path.exists('/Users')) 4 | print( os.path.isdir('/Users')) 5 | os.path.join('/tmp/a/','b/c') 6 | 7 | from pathlib import Path 8 | p = Path('.') 9 | print ( p.resolve()) 10 | 11 | p.is_dir() 12 | 13 | q = Path('/tmp/a/b/c') 14 | 15 | Path.mkdir(q,parents=True) 16 | 17 | -------------------------------------------------------------------------------- /timegeekbang.com/exception_handling.py: -------------------------------------------------------------------------------- 1 | # i = j 2 | 3 | 4 | # print()) 5 | 6 | 7 | # a='123' 8 | # print(a[3]) 9 | # 10 | # d = {'a':1 ,'b':2} 11 | # print(d['c']) 12 | 13 | # 14 | # year = int(input('input year:')) 15 | 16 | # try: 17 | # year = int(input('input year:')) 18 | # except ValueError: 19 | # print('年份要输入数字') 20 | # 21 | # a=123 22 | # a.append() 23 | 24 | # except (ValueError, AttributeError, KeyError) 25 | 26 | # 27 | # try: 28 | # print(1/'a') 29 | # except Exception as e: 30 | # print(' %s' %e) 31 | # 32 | # try: 33 | # raise NameError('helloError') 34 | # except NameError: 35 | # print('my custom error') 36 | 37 | 38 | try: 39 | a = open('name.txt') 40 | except Exception as e: 41 | print(e) 42 | 43 | finally: 44 | a.close() 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /timegeekbang.com/file_op.py: -------------------------------------------------------------------------------- 1 | # 将小说的主要人物记录在文件中 2 | # file1 = open('name.txt','w') 3 | # file1.write('诸葛亮') 4 | # file1.close() 5 | # 6 | # 7 | # file2 = open('name.txt') 8 | # print(file2.read()) 9 | # 10 | # file2.close() 11 | # 12 | # file3 = open('name.txt','a') 13 | # file3.write('刘备') 14 | # file3.close() 15 | # 16 | # file4 = open('name.txt') 17 | # print (file4.readline()) 18 | # 19 | # file5 = open('name.txt') 20 | # for line in file5.readlines(): 21 | # print(line) 22 | # print('=====') 23 | # 24 | # 25 | 26 | file6 = open('name.txt') 27 | print('当前文件指针的位置 %s' %file6.tell()) 28 | print ( '当前读取到了一个字符,字符的内容是 %s' %file6.read(1)) 29 | print('当前文件指针的位置 %s' %file6.tell()) 30 | # 第一个参数代表偏移位置,第二个参数 0 表示从文件开头偏移 1表示从当前位置偏移, 2 从文件结尾 31 | file6.seek(5,0) 32 | print('我们进行了seek操作') 33 | print('当前文件指针的位置 %s' %file6.tell()) 34 | print ( '当前读取到了一个字符,字符的内容是 %s' %file6.read(1)) 35 | print('当前文件指针的位置 %s' %file6.tell()) 36 | file6.close() 37 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test.py: -------------------------------------------------------------------------------- 1 | # print('abc',end='\n') 2 | # print('abc') 3 | # 4 | # def func (a, b, c): 5 | # print('a= %s' %a) 6 | # print('b= %s' %b) 7 | # print('c= %s' %c) 8 | # 9 | # 10 | # func(1, c=3) 11 | 12 | 13 | 14 | # # 取得参数的个数 15 | # def howlong(first, *other): 16 | # print( 1 + len(other)) 17 | # 18 | # howlong() 19 | 20 | # 21 | # var1 = 123 22 | # 23 | # def func(): 24 | # global var1 25 | # var1 = 456 26 | # print(var1) 27 | # 28 | # 29 | # 30 | # func() 31 | # print(var1) 32 | 33 | # iter() next() 34 | 35 | # list1 =[1, 2, 3] 36 | # it = iter(list1) 37 | # # print( next(it)) 38 | # # print( next(it)) 39 | # # print( next(it)) 40 | # # print( next(it)) # except 41 | # # 42 | # 43 | # 44 | # 45 | # # for i in range(10,20,0.5): 46 | # # print(i) 47 | # # 48 | # # def frange(start, stop, step): 49 | # # x = start 50 | # # while x < stop: 51 | # # yield x 52 | # # x += step 53 | # # 54 | # # 55 | # # for i in frange(10,20,0.5): 56 | # # print(i) 57 | # # 58 | # # 59 | # # 60 | # # 61 | # # 62 | # # 63 | # # def true():return True 64 | # # lambda : True 65 | # # 66 | # # 67 | # # >>> def add(x,y): 68 | # # ... return x+y 69 | # # ... 70 | # # 71 | # # >>> def add(x,y): return x+y 72 | # # lambda x,y: x+y 73 | # # 74 | # # 75 | # # >>> add(3,5) 76 | # # 8 77 | # # >>> 78 | # 79 | # 80 | # 81 | # # lambda x:x<= (month, day) 82 | # # 83 | # # def func1(x): 84 | # # return x<= (month, day) 85 | # # 86 | # # 87 | # # 88 | # # lambda item:item[1] 89 | # # 90 | # # def func2(item): 91 | # # return item[1] 92 | # # 93 | # # 94 | # # filter() map() reduce() zip() 95 | # # 96 | # 97 | # 98 | # a=[1,2,3,4,5,6,7] 99 | # list(filter(lambda x:x>2 , a)) 100 | # 101 | # >>> help(filter) 102 | # 103 | # >>> a=[1,2,3,4,5,6,7] 104 | # >>> list(filter(lambda x:x>2 , a)) 105 | # [3, 4, 5, 6, 7] 106 | # >>> help(map) 107 | # 108 | # >>> a=[1,2,3] 109 | # >>> map(lambda x:x ,a) 110 | # 111 | # >>> list(map(lambda x:x ,a)) 112 | # [1, 2, 3] 113 | # >>> list(map(lambda x:x+1 ,a)) 114 | # [2, 3, 4] 115 | # >>> b=[4,5,6] 116 | # >>> list(map(lambda x,y:x+y ,a,b)) 117 | # [5, 7, 9] 118 | # >>> 119 | # >>> 120 | # >>> 121 | # >>> 122 | # >>> 123 | # >>> [1, 2, 3] 124 | # [1, 2, 3] 125 | # >>> [4, 5, 6] 126 | # [4, 5, 6] 127 | # >>> help(reduce) 128 | # Traceback (most recent call last): 129 | # File "", line 1, in 130 | # NameError: name 'reduce' is not defined 131 | # >>> from functools import reduce 132 | # 133 | # 134 | # >>> from functools import reduce 135 | # >>> reduce(lambda x,y: x+y ,[2,3,4],1 ) 136 | # 10 137 | # >>> ((1+2)+3)+4 138 | # 139 | # >>> for i in zip((1,2,3),(4,5,6)): 140 | # ... print(i) 141 | # ... 142 | # (1, 4) 143 | # (2, 5) 144 | # (3, 6) 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | def func(): 174 | a = 1 175 | b = 2 176 | return a+b 177 | 178 | 179 | def sum(a): 180 | def add(b): 181 | return a+b 182 | 183 | return add 184 | 185 | # add 函数名称或函数的引用 186 | # add() 函数的调用 187 | 188 | num1 = func() 189 | 190 | num2 = sum(2) 191 | print( num2(4)) 192 | 193 | # 194 | # print(type(num1)) 195 | # print(type(num2)) 196 | # 197 | 198 | count() 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test2.py: -------------------------------------------------------------------------------- 1 | def counter(FIRST=0): 2 | cnt = [FIRST] 3 | 4 | def add_one(): 5 | cnt[0] += 1 6 | return cnt[0] 7 | 8 | return add_one 9 | 10 | 11 | num5 = counter(5) 12 | num10 = counter(10) 13 | 14 | print(num5()) 15 | print(num5()) 16 | print(num5()) 17 | print(num10()) 18 | print(num10()) 19 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test3.py: -------------------------------------------------------------------------------- 1 | # a * x + b = y 2 | 3 | def a_line(a,b): 4 | def arg_y(x): 5 | return a*x+b 6 | return arg_y 7 | 8 | 9 | def a_line(a,b): 10 | return lambda x: a*x+b 11 | return arg_y 12 | 13 | 14 | # a=3 b=5 15 | # x=10 y=? 16 | # x=20 y =? 17 | 18 | # a=5 b=10 19 | 20 | line1 = a_line(3, 5) 21 | line2 = a_line(5,10) 22 | 23 | print (line1(10)) 24 | print (line1(20)) 25 | 26 | #def func1( a,b, x) 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test4.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | # print( time.time()) 4 | 5 | def timmer(func): 6 | def wrapper(): 7 | start_time = time.time() 8 | func() 9 | stop_time = time.time() 10 | print("运行时间是 %s 秒 " % (stop_time - start_time)) 11 | return wrapper 12 | 13 | 14 | 15 | @timmer 16 | def i_can_sleep(): 17 | time.sleep(3) 18 | 19 | 20 | 21 | 22 | # start_time = time.time() 23 | i_can_sleep() 24 | 25 | # stop_time = time.time() 26 | 27 | # print('函数运行了 %s 秒' %(stop_time-start_time)) 28 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test5.py: -------------------------------------------------------------------------------- 1 | def new_tips(argv): 2 | def tips(func): 3 | def nei(a, b): 4 | print('start %s %s' % (argv, func.__name__)) 5 | func(a, b) 6 | print('stop') 7 | 8 | return nei 9 | return tips 10 | 11 | 12 | @new_tips('add_module') 13 | def add(a, b): 14 | print(a + b) 15 | 16 | 17 | @new_tips('sub_module') 18 | def sub(a, b): 19 | print(a - b) 20 | 21 | 22 | print(add(4, 5)) 23 | print(sub(7, 3)) 24 | -------------------------------------------------------------------------------- /timegeekbang.com/func_test6.py: -------------------------------------------------------------------------------- 1 | fd = open('name.txt') 2 | try: 3 | for line in fd: 4 | print (line) 5 | finally: 6 | fd.close() 7 | 8 | 9 | with open('name.txt') as f: 10 | for line in f: 11 | print(line) 12 | -------------------------------------------------------------------------------- /timegeekbang.com/hello_world.py: -------------------------------------------------------------------------------- 1 | # 这是我的第一个Python程序 2 | 3 | import time # 我导入了一个时间模块 4 | 5 | 6 | print(time.time()) #在屏幕上打印出从1970年1月1日0:00 到现在经过了多少秒 7 | 8 | if 10-9 > 0: 9 | # 这行需要缩进,缩进用4个空格 10 | print('10大于9') -------------------------------------------------------------------------------- /timegeekbang.com/iris_test.csv: -------------------------------------------------------------------------------- 1 | 30,4,setosa,versicolor,virginica 2 | 5.9,3.0,4.2,1.5,1 3 | 6.9,3.1,5.4,2.1,2 4 | 5.1,3.3,1.7,0.5,0 5 | 6.0,3.4,4.5,1.6,1 6 | 5.5,2.5,4.0,1.3,1 7 | 6.2,2.9,4.3,1.3,1 8 | 5.5,4.2,1.4,0.2,0 9 | 6.3,2.8,5.1,1.5,2 10 | 5.6,3.0,4.1,1.3,1 11 | 6.7,2.5,5.8,1.8,2 12 | 7.1,3.0,5.9,2.1,2 13 | 4.3,3.0,1.1,0.1,0 14 | 5.6,2.8,4.9,2.0,2 15 | 5.5,2.3,4.0,1.3,1 16 | 6.0,2.2,4.0,1.0,1 17 | 5.1,3.5,1.4,0.2,0 18 | 5.7,2.6,3.5,1.0,1 19 | 4.8,3.4,1.9,0.2,0 20 | 5.1,3.4,1.5,0.2,0 21 | 5.7,2.5,5.0,2.0,2 22 | 5.4,3.4,1.7,0.2,0 23 | 5.6,3.0,4.5,1.5,1 24 | 6.3,2.9,5.6,1.8,2 25 | 6.3,2.5,4.9,1.5,1 26 | 5.8,2.7,3.9,1.2,1 27 | 6.1,3.0,4.6,1.4,1 28 | 5.2,4.1,1.5,0.1,0 29 | 6.7,3.1,4.7,1.5,1 30 | 6.7,3.3,5.7,2.5,2 31 | 6.4,2.9,4.3,1.3,1 32 | -------------------------------------------------------------------------------- /timegeekbang.com/iris_training.csv: -------------------------------------------------------------------------------- 1 | 120,4,setosa,versicolor,virginica 2 | 6.4,2.8,5.6,2.2,2 3 | 5.0,2.3,3.3,1.0,1 4 | 4.9,2.5,4.5,1.7,2 5 | 4.9,3.1,1.5,0.1,0 6 | 5.7,3.8,1.7,0.3,0 7 | 4.4,3.2,1.3,0.2,0 8 | 5.4,3.4,1.5,0.4,0 9 | 6.9,3.1,5.1,2.3,2 10 | 6.7,3.1,4.4,1.4,1 11 | 5.1,3.7,1.5,0.4,0 12 | 5.2,2.7,3.9,1.4,1 13 | 6.9,3.1,4.9,1.5,1 14 | 5.8,4.0,1.2,0.2,0 15 | 5.4,3.9,1.7,0.4,0 16 | 7.7,3.8,6.7,2.2,2 17 | 6.3,3.3,4.7,1.6,1 18 | 6.8,3.2,5.9,2.3,2 19 | 7.6,3.0,6.6,2.1,2 20 | 6.4,3.2,5.3,2.3,2 21 | 5.7,4.4,1.5,0.4,0 22 | 6.7,3.3,5.7,2.1,2 23 | 6.4,2.8,5.6,2.1,2 24 | 5.4,3.9,1.3,0.4,0 25 | 6.1,2.6,5.6,1.4,2 26 | 7.2,3.0,5.8,1.6,2 27 | 5.2,3.5,1.5,0.2,0 28 | 5.8,2.6,4.0,1.2,1 29 | 5.9,3.0,5.1,1.8,2 30 | 5.4,3.0,4.5,1.5,1 31 | 6.7,3.0,5.0,1.7,1 32 | 6.3,2.3,4.4,1.3,1 33 | 5.1,2.5,3.0,1.1,1 34 | 6.4,3.2,4.5,1.5,1 35 | 6.8,3.0,5.5,2.1,2 36 | 6.2,2.8,4.8,1.8,2 37 | 6.9,3.2,5.7,2.3,2 38 | 6.5,3.2,5.1,2.0,2 39 | 5.8,2.8,5.1,2.4,2 40 | 5.1,3.8,1.5,0.3,0 41 | 4.8,3.0,1.4,0.3,0 42 | 7.9,3.8,6.4,2.0,2 43 | 5.8,2.7,5.1,1.9,2 44 | 6.7,3.0,5.2,2.3,2 45 | 5.1,3.8,1.9,0.4,0 46 | 4.7,3.2,1.6,0.2,0 47 | 6.0,2.2,5.0,1.5,2 48 | 4.8,3.4,1.6,0.2,0 49 | 7.7,2.6,6.9,2.3,2 50 | 4.6,3.6,1.0,0.2,0 51 | 7.2,3.2,6.0,1.8,2 52 | 5.0,3.3,1.4,0.2,0 53 | 6.6,3.0,4.4,1.4,1 54 | 6.1,2.8,4.0,1.3,1 55 | 5.0,3.2,1.2,0.2,0 56 | 7.0,3.2,4.7,1.4,1 57 | 6.0,3.0,4.8,1.8,2 58 | 7.4,2.8,6.1,1.9,2 59 | 5.8,2.7,5.1,1.9,2 60 | 6.2,3.4,5.4,2.3,2 61 | 5.0,2.0,3.5,1.0,1 62 | 5.6,2.5,3.9,1.1,1 63 | 6.7,3.1,5.6,2.4,2 64 | 6.3,2.5,5.0,1.9,2 65 | 6.4,3.1,5.5,1.8,2 66 | 6.2,2.2,4.5,1.5,1 67 | 7.3,2.9,6.3,1.8,2 68 | 4.4,3.0,1.3,0.2,0 69 | 7.2,3.6,6.1,2.5,2 70 | 6.5,3.0,5.5,1.8,2 71 | 5.0,3.4,1.5,0.2,0 72 | 4.7,3.2,1.3,0.2,0 73 | 6.6,2.9,4.6,1.3,1 74 | 5.5,3.5,1.3,0.2,0 75 | 7.7,3.0,6.1,2.3,2 76 | 6.1,3.0,4.9,1.8,2 77 | 4.9,3.1,1.5,0.1,0 78 | 5.5,2.4,3.8,1.1,1 79 | 5.7,2.9,4.2,1.3,1 80 | 6.0,2.9,4.5,1.5,1 81 | 6.4,2.7,5.3,1.9,2 82 | 5.4,3.7,1.5,0.2,0 83 | 6.1,2.9,4.7,1.4,1 84 | 6.5,2.8,4.6,1.5,1 85 | 5.6,2.7,4.2,1.3,1 86 | 6.3,3.4,5.6,2.4,2 87 | 4.9,3.1,1.5,0.1,0 88 | 6.8,2.8,4.8,1.4,1 89 | 5.7,2.8,4.5,1.3,1 90 | 6.0,2.7,5.1,1.6,1 91 | 5.0,3.5,1.3,0.3,0 92 | 6.5,3.0,5.2,2.0,2 93 | 6.1,2.8,4.7,1.2,1 94 | 5.1,3.5,1.4,0.3,0 95 | 4.6,3.1,1.5,0.2,0 96 | 6.5,3.0,5.8,2.2,2 97 | 4.6,3.4,1.4,0.3,0 98 | 4.6,3.2,1.4,0.2,0 99 | 7.7,2.8,6.7,2.0,2 100 | 5.9,3.2,4.8,1.8,1 101 | 5.1,3.8,1.6,0.2,0 102 | 4.9,3.0,1.4,0.2,0 103 | 4.9,2.4,3.3,1.0,1 104 | 4.5,2.3,1.3,0.3,0 105 | 5.8,2.7,4.1,1.0,1 106 | 5.0,3.4,1.6,0.4,0 107 | 5.2,3.4,1.4,0.2,0 108 | 5.3,3.7,1.5,0.2,0 109 | 5.0,3.6,1.4,0.2,0 110 | 5.6,2.9,3.6,1.3,1 111 | 4.8,3.1,1.6,0.2,0 112 | 6.3,2.7,4.9,1.8,2 113 | 5.7,2.8,4.1,1.3,1 114 | 5.0,3.0,1.6,0.2,0 115 | 6.3,3.3,6.0,2.5,2 116 | 5.0,3.5,1.6,0.6,0 117 | 5.5,2.6,4.4,1.2,1 118 | 5.7,3.0,4.2,1.2,1 119 | 4.4,2.9,1.4,0.2,0 120 | 4.8,3.0,1.4,0.1,0 121 | 5.5,2.4,3.7,1.0,1 122 | -------------------------------------------------------------------------------- /timegeekbang.com/mod_test.py: -------------------------------------------------------------------------------- 1 | import mymod 2 | 3 | mymod.print_me() -------------------------------------------------------------------------------- /timegeekbang.com/mymod.py: -------------------------------------------------------------------------------- 1 | def print_me(): 2 | print('me') 3 | 4 | 5 | # print_me() 6 | 7 | https://www.python.org/dev/peps/pep-0008/ 8 | 9 | 10 | 11 | pycharm 安装PEP8 12 | cmd窗口输入:pip install autopep8 13 | Tools→Extends Tools→点击加号 14 | 15 | Name:Autopep8(可以随便取) 16 | - Tools settings: 17 | - Programs:`autopep8` (前提是你已经安装了哦) 18 | - Parameters:`--in-place --aggressive --aggressive $FilePath$` 19 | - Working directory:`$ProjectFileDir$` 20 | - 点击Output Filters→添加,在对话框中的:Regular expression to match output中输入:`$FILE_PATH$\:$LINE$\:$COLUMN$\:.*` 21 | 22 | -------------------------------------------------------------------------------- /timegeekbang.com/name.txt: -------------------------------------------------------------------------------- 1 | 諸葛亮|關羽|劉備|曹操|孫權|關羽|張飛|呂布|周瑜|趙雲|龐統|司馬懿|黃忠|馬超 -------------------------------------------------------------------------------- /timegeekbang.com/network_bandwidth.py: -------------------------------------------------------------------------------- 1 | # 网络带宽计算 2 | # print(100/8) 3 | 4 | bandwidth = 100 5 | ratio = 8 6 | 7 | print(bandwidth/ratio) 8 | 9 | bandWidth 10 | BandWidth 11 | band_width 12 | -------------------------------------------------------------------------------- /timegeekbang.com/numpy_test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | arr1 =np.array([2,3,4]) 4 | 5 | # print( arr1) 6 | # print ( arr1.dtype) 7 | # 8 | # arr2 = np.array([ 1.2, 2.3 , 3.4]) 9 | # 10 | # print( arr2) 11 | # print( arr2.dtype) 12 | # 13 | # print ( arr1 + arr2) 14 | # 15 | # print( arr2 * 10 ) 16 | # 17 | # 18 | # data = [[1,2,3], [4,5,6]] 19 | # arr3 = np.array(data) 20 | # print( arr3) 21 | # print ( arr3.dtype) 22 | # 23 | # print (np.zeros((3,5))) 24 | # 25 | # print( np.ones((4,6))) 26 | # 27 | # print(np.empty((2,3,2))) 28 | 29 | arr4 = np.arange(10) 30 | 31 | arr4[5:8] = 10 32 | 33 | print(arr4) 34 | 35 | arr_slice = arr4[5:8].copy() 36 | 37 | arr_slice[:] = 15 38 | 39 | print(arr_slice) 40 | print(arr4) -------------------------------------------------------------------------------- /timegeekbang.com/pachong1.py: -------------------------------------------------------------------------------- 1 | from urllib import request 2 | 3 | url ='http://www.baidu.com' 4 | response = request.urlopen(url,timeout=1) 5 | print (response.read().decode('utf-8')) 6 | -------------------------------------------------------------------------------- /timegeekbang.com/pachong2.py: -------------------------------------------------------------------------------- 1 | from urllib import parse 2 | from urllib import request 3 | 4 | data = bytes(parse.urlencode({'word':'hello'}),encoding='utf8') 5 | # print(data) 6 | 7 | response = request.urlopen('http://httpbin.org/post', data=data) 8 | print(response.read().decode('utf-8')) 9 | 10 | 11 | response2 = request.urlopen('http://httpbin.org/get', timeout=1) 12 | print(response2.read()) 13 | 14 | 15 | # response3 = request.urlopen('http://httpbin.org/get', timeout=0.1) 16 | 17 | import urllib 18 | import socket 19 | 20 | 21 | try: 22 | response3 = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1) 23 | except urllib.error.URLError as e: 24 | if isinstance(e.reason, socket.timeout): 25 | print('TIME OUT') -------------------------------------------------------------------------------- /timegeekbang.com/pachong3.py: -------------------------------------------------------------------------------- 1 | from urllib import request, parse 2 | 3 | url = 'http://httpbin.org/post' 4 | 5 | headers = { 6 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 7 | "Accept-Encoding": "gzip, deflate, sdch", 8 | "Accept-Language": "zh-CN,zh;q=0.8", 9 | "Connection": "close", 10 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 11 | "Referer": "http://httpbin.org/", 12 | "Upgrade-Insecure-Requests": "1", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 14 | } 15 | 16 | dict = { 17 | 'name': 'value' 18 | } 19 | 20 | data = bytes(parse.urlencode(dict), encoding='utf8') 21 | req = request.Request(url=url, data=data, headers=headers, method='POST') 22 | response = request.urlopen(req) 23 | print(response.read().decode('utf-8')) -------------------------------------------------------------------------------- /timegeekbang.com/pachong4.py: -------------------------------------------------------------------------------- 1 | # get请求 2 | import requests 3 | url = 'http://httpbin.org/get' 4 | data = {'key': 'value', 'abc': 'xyz'} 5 | # .get是使用get方式请求url,字典类型的data不用进行额外处理 6 | response = requests.get(url, data) 7 | print(response.text) 8 | 9 | 10 | # post请求 11 | import requests 12 | url = 'http://httpbin.org/post' 13 | data = {'key': 'value', 'abc': 'xyz'} 14 | # .post表示为post方法 15 | response = requests.post(url, data) 16 | # 返回类型为json格式 17 | print(response.json()) -------------------------------------------------------------------------------- /timegeekbang.com/pachong5.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import re 3 | content = requests.get('http://www.cnu.cc/discoveryPage/hot-人像').text 4 | 5 | # print(content) 6 | 7 | 8 | # < div class ="grid-item work-thumbnail" > 9 | # < a href="(.*?)".*?title">(.*?) 10 | # < div class ="author" > LynnWei < / div > 11 | 12 | pattern = re.compile(r'(.*?)', re.S) 13 | results = re.findall(pattern, content) 14 | # print(results) 15 | 16 | 17 | for result in results: 18 | url, name = result 19 | print(url, re.sub('\s', '', name)) -------------------------------------------------------------------------------- /timegeekbang.com/pachong6.py: -------------------------------------------------------------------------------- 1 | html_doc = """ 2 | The Dormouse's story 3 | 4 |

The Dormouse's story

5 | 6 |

Once upon a time there were three little sisters; and their names were 7 | Elsie, 8 | Lacie and 9 | Tillie; 10 | and they lived at the bottom of a well.

11 | 12 |

...

13 | """ 14 | 15 | from bs4 import BeautifulSoup 16 | 17 | soup = BeautifulSoup(html_doc, 'lxml') 18 | 19 | print(soup.prettify()) 20 | 21 | # 22 | # # 找到title标签 23 | # print(soup.title) 24 | # 25 | # # title 标签里的内容 26 | # print(soup.title.string) 27 | 28 | 29 | # # 找到p标签 30 | print(soup.p) 31 | # 32 | # # 找到p标签class的名字 33 | # print(soup.p['class']) 34 | # 35 | # # 找到第一个a标签 36 | # print(soup.a) 37 | # 38 | # # 找到所有的a标签 39 | # print(soup.find_all('a')) 40 | # 41 | # 42 | # # 找到id为link3的的标签 43 | print(soup.find(id="link3")) 44 | # 45 | # # 找到所有标签的链接 46 | # for link in soup.find_all('a'): 47 | # print(link.get('href')) 48 | # 49 | # # 找到文档中所有的文本内容 50 | # print(soup.get_text()) -------------------------------------------------------------------------------- /timegeekbang.com/pachong7.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | 4 | headers = { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Language": "zh-CN,zh;q=0.8", 7 | "Connection": "close", 8 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 9 | "Referer": "http://www.infoq.com", 10 | "Upgrade-Insecure-Requests": "1", 11 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 12 | } 13 | 14 | url = 'http://www.infoq.com/cn/news' 15 | 16 | 17 | 18 | # 取得新闻标题 19 | def craw2(url): 20 | response = requests.get(url, headers=headers) 21 | 22 | soup = BeautifulSoup(response.text, 'lxml') 23 | 24 | for title_href in soup.find_all('div', class_='news_type_block'): 25 | print([title.get('title') 26 | for title in title_href.find_all('a') if title.get('title')]) 27 | 28 | # craw2(url) 29 | 30 | 31 | 32 | # 翻页 33 | for i in range(15, 46, 15): 34 | url = 'http://www.infoq.com/cn/news/' + str(i) 35 | # print(url) 36 | craw2(url) -------------------------------------------------------------------------------- /timegeekbang.com/pachong8.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | import os 4 | import shutil 5 | 6 | headers = { 7 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 8 | "Accept-Language": "zh-CN,zh;q=0.8", 9 | "Connection": "close", 10 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 11 | "Referer": "http://www.infoq.com", 12 | "Upgrade-Insecure-Requests": "1", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 14 | } 15 | 16 | url = 'http://www.infoq.com/cn/presentations' 17 | 18 | 19 | # 下载图片 20 | # Requests 库封装复杂的接口,提供更人性化的 HTTP 客户端,但不直接提供下载文件的函数。 21 | # 需要通过为请求设置特殊参数 stream 来实现。当 stream 设为 True 时, 22 | # 上述请求只下载HTTP响应头,并保持连接处于打开状态, 23 | # 直到访问 Response.content 属性时才开始下载响应主体内容 24 | 25 | 26 | def download_jpg(image_url, image_localpath): 27 | response = requests.get(image_url, stream=True) 28 | if response.status_code == 200: 29 | with open(image_localpath, 'wb') as f: 30 | response.raw.deconde_content = True 31 | shutil.copyfileobj(response.raw, f) 32 | 33 | 34 | # 取得演讲图片 35 | def craw3(url): 36 | response = requests.get(url, headers=headers) 37 | soup = BeautifulSoup(response.text, 'lxml') 38 | for pic_href in soup.find_all('div', class_='news_type_video'): 39 | for pic in pic_href.find_all('img'): 40 | imgurl = pic.get('src') 41 | dir = os.path.abspath('.') 42 | filename = os.path.basename(imgurl) 43 | imgpath = os.path.join(dir, filename) 44 | print('开始下载 %s' % imgurl) 45 | download_jpg(imgurl, imgpath) 46 | 47 | 48 | # craw3(url) 49 | # 50 | # 翻页 51 | j = 0 52 | for i in range(12, 37, 12): 53 | url = 'http://www.infoq.com/cn/presentations' + str(i) 54 | j += 1 55 | print('第 %d 页' % j) 56 | craw3(url) 57 | -------------------------------------------------------------------------------- /timegeekbang.com/pachong_infoq.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | 4 | headers = { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Language": "zh-CN,zh;q=0.8", 7 | "Connection": "close", 8 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 9 | "Referer": "http://www.infoq.com", 10 | "Upgrade-Insecure-Requests": "1", 11 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 12 | } 13 | 14 | url = 'https://www.infoq.com/news/' 15 | 16 | # 取得网页完整内容 17 | 18 | 19 | def craw(url): 20 | response = requests.get(url, headers=headers) 21 | print(response.text) 22 | 23 | # craw(url) 24 | 25 | # 取得新闻标题 26 | 27 | 28 | def craw2(url): 29 | response = requests.get(url, headers=headers) 30 | 31 | soup = BeautifulSoup(response.text, 'lxml') 32 | 33 | for title_href in soup.find_all('div', class_='items__content'): 34 | print([title.get('title') 35 | for title in title_href.find_all('a') if title.get('title')]) 36 | 37 | # craw2(url) 38 | 39 | 40 | # 翻页 41 | for i in range(15, 46, 15): 42 | url = 'http://www.infoq.com/news/' + str(i) 43 | # print(url) 44 | craw2(url) 45 | -------------------------------------------------------------------------------- /timegeekbang.com/pachong_infoq2.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | import os 4 | import shutil 5 | 6 | headers = { 7 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 8 | "Accept-Language": "zh-CN,zh;q=0.8", 9 | "Connection": "close", 10 | "Cookie": "_gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1", 11 | "Referer": "http://www.infoq.com", 12 | "Upgrade-Insecure-Requests": "1", 13 | "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER" 14 | } 15 | 16 | url = 'http://www.infoq.com/presentations' 17 | 18 | 19 | # 下载图片 20 | # Requests 库封装复杂的接口,提供更人性化的 HTTP 客户端,但不直接提供下载文件的函数。 21 | # 需要通过为请求设置特殊参数 stream 来实现。当 stream 设为 True 时, 22 | # 上述请求只下载HTTP响应头,并保持连接处于打开状态, 23 | # 直到访问 Response.content 属性时才开始下载响应主体内容 24 | 25 | 26 | def download_jpg(image_url, image_localpath): 27 | response = requests.get(image_url, stream=True) 28 | if response.status_code == 200: 29 | with open(image_localpath, 'wb') as f: 30 | response.raw.deconde_content = True 31 | shutil.copyfileobj(response.raw, f) 32 | 33 | 34 | # 取得演讲图片 35 | def craw3(url): 36 | response = requests.get(url, headers=headers) 37 | soup = BeautifulSoup(response.text, 'lxml') 38 | for pic_href in soup.find_all('div', class_='items__content'): 39 | for pic in pic_href.find_all('img'): 40 | imgurl = pic.get('src') 41 | dir = os.path.abspath('.') 42 | filename = os.path.basename(imgurl) 43 | imgpath = os.path.join(dir, filename) 44 | print('开始下载 %s' % imgurl) 45 | download_jpg(imgurl, imgpath) 46 | 47 | 48 | # craw3(url) 49 | 50 | # 翻页 51 | j = 0 52 | for i in range(12, 37, 12): 53 | url = 'http://www.infoq.com/presentations' + str(i) 54 | j += 1 55 | print('第 %d 页' % j) 56 | craw3(url) 57 | -------------------------------------------------------------------------------- /timegeekbang.com/pandas_test.py: -------------------------------------------------------------------------------- 1 | from pandas import Series, DataFrame 2 | import pandas as pd 3 | 4 | 5 | obj = Series([4, 5, 6, -7]) 6 | 7 | # print(obj) 8 | # 9 | # print( obj.index) 10 | # 11 | # print ( obj.values) 12 | # 13 | # 14 | # {['a']:1} 15 | # 16 | 17 | obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'c', 'a']) 18 | 19 | # print(obj2) 20 | # 21 | # obj2['c'] = 6 22 | # 23 | # print(obj2) 24 | # 25 | # print ('f' in obj2) 26 | 27 | 28 | sdata = { 29 | 'beijing': 35000, 30 | 'shanghai': 71000, 31 | 'guangzhou': 16000, 32 | 'shenzhen': 5000} 33 | obj3 = Series(sdata) 34 | # print( obj3) 35 | 36 | obj3.index = ['bj', 'gz', 'sh', 'sz'] 37 | # 38 | # print( obj3) 39 | 40 | 41 | data = {'city': ['shanghai', 'shanghai', 'shanghai', 'beijing', 'beijing'], 42 | 'year': [2016, 2017, 2018, 2017, 2018], 43 | 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} 44 | 45 | frame = DataFrame(data) 46 | 47 | frame2 = DataFrame(data, columns=['year', 'city', 'pop']) 48 | 49 | 50 | # print(frame) 51 | # 52 | # print(frame2) 53 | # 54 | # print(frame2['city']) 55 | # print(frame2.year) 56 | frame2['new'] = 100 57 | 58 | # print(frame2) 59 | 60 | frame2['cap'] = frame2.city == 'beijing' 61 | 62 | # print( frame2) 63 | 64 | pop = {'beijing': {2008: 1.5, 2009: 2.0}, 65 | 'shanghai': {2008: 2.0, 2009: 3.6} 66 | } 67 | 68 | frame3 = DataFrame(pop) 69 | print(frame3.T) 70 | 71 | obj4 = Series([4.5, 7.2, -5.3, 3.6], index=['b', 'd', 'c', 'a']) 72 | 73 | obj5 = obj4.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0) 74 | 75 | print(obj5) 76 | 77 | obj6 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4]) 78 | 79 | # 80 | # print( obj6.reindex(range(6),method='bfill')) 81 | 82 | from numpy import nan as NA 83 | 84 | data = Series([1, NA, 2]) 85 | # print(data.dropna()) 86 | 87 | # data2 = DataFrame([[1., 6.5, 3], [1., NA, NA], [NA, NA, NA] 88 | # ]) 89 | # data2[4] = NA 90 | # print(data2) 91 | # print(data2.dropna(axis=1, how='all')) 92 | # 93 | # data2.fillna(0) 94 | # print(data2.fillna(0, inplace=True)) 95 | # print(data2) 96 | 97 | import numpy as np 98 | 99 | data3 = Series(np.random.randn(10), 100 | index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'], 101 | [1, 2, 3, 1, 2, 3, 1, 2, 2, 3]]) 102 | 103 | print( data3.unstack().stack() ) 104 | 105 | # print ( data3['b':'c']) 106 | -------------------------------------------------------------------------------- /timegeekbang.com/plt_test.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | # 3 | # #绘制简单的曲线 4 | # plt.plot([1, 3, 5], [4, 8, 10]) 5 | # plt.show() 6 | 7 | import numpy as np 8 | 9 | # x= np.linspace(-np.pi,np.pi,100) # x轴的定义域为 -3.14~3.14,中间间隔100个元素 10 | # plt.plot(x,np.sin(x)) 11 | # #显示所画的图 12 | # plt.show() 13 | 14 | # x = np.linspace(-np.pi * 2, np.pi * 2, 100) # 定义域为: -2pi 到 2pi 15 | # plt.figure(1, dpi=50) # 创建图表1 16 | # for i in range(1, 5): # 画四条线 17 | # plt.plot(x, np.sin(x / i)) 18 | # plt.show() 19 | # 20 | # plt.figure(1, dpi=50) # 创建图表1,dpi代表图片精细度,dpi越大文件越大,杂志要300以上 21 | # data = [1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 4] 22 | # plt.hist(data) # 只要传入数据,直方图就会统计数据出现的次数 23 | # 24 | # plt.show() 25 | 26 | # x = np.arange(1,10) 27 | # y = x 28 | # fig = plt.figure() 29 | # plt.scatter(x,y,c = 'r',marker = 'o') #c = 'r'表示散点的颜色为红色,marker 表示指定三点多形状为圆形 30 | # plt.show() 31 | 32 | 33 | # import matplotlib.pyplot as plt 34 | # import numpy as np 35 | # import pandas as pd 36 | # 37 | # iris = pd.read_csv("./iris_training.csv") 38 | # print (iris.head() ) 39 | # 40 | # #绘制散点图 41 | # iris.plot(kind="scatter", x="120", y="4") 42 | # 43 | # # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 44 | # plt.show() 45 | # 46 | # import matplotlib.pyplot as plt 47 | # import numpy as np 48 | # import pandas as pd 49 | # import seaborn as sns 50 | # 51 | # iris = pd.read_csv("./iris_training.csv") 52 | # #设置样式 53 | # sns.set(style="white", color_codes=True) 54 | # # 设置绘制格式为散点图 55 | # sns.jointplot(x="120", y="4", data=iris, size=5) 56 | # # distplot绘制曲线 57 | # sns.distplot(iris['120']) 58 | # 59 | # # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 60 | # plt.show() 61 | 62 | import matplotlib.pyplot as plt 63 | import pandas as pd 64 | import seaborn as sns 65 | 66 | import warnings 67 | warnings.filterwarnings("ignore") 68 | 69 | iris = pd.read_csv("./iris_training.csv") 70 | 71 | sns.set(style="white", color_codes=True) 72 | 73 | 74 | # FacetGrid 一般绘图函数 75 | # hue 彩色显示分类0/1/2 76 | # plt.scatter 绘制散点图 77 | # add_legend() 显示分类的描述信息 78 | # sns.FacetGrid(iris, hue="virginica", size=5).map(plt.scatter, "120", "4").add_legend() 79 | 80 | sns.FacetGrid(iris, hue="virginica", size=5).map(plt.scatter, "setosa", "versicolor").add_legend() 81 | # 没啥用,只是让pandas 的plot() 方法在pyCharm上显示 82 | plt.show() -------------------------------------------------------------------------------- /timegeekbang.com/sanguo.py: -------------------------------------------------------------------------------- 1 | 2 | # 读取人物名称 3 | f = open('name.txt') 4 | data = f.read() 5 | data0 = data.split('|') 6 | 7 | # 读取兵器名称 8 | f2 = open('weapon.txt') 9 | # data2 = f2.read() 10 | i = 1 11 | for line in f2.readlines(): 12 | if i % 2 == 1: 13 | print(line.strip('\n')) 14 | i += 1 15 | 16 | f3 = open('sanguo.txt',encoding='GB18030') 17 | print(f3.read().replace('\n','')) 18 | # 19 | # 20 | # def func(filename): 21 | # print(open(filename).read()) 22 | # print('test func') 23 | # 24 | # 25 | # 26 | # func('name.txt') 27 | -------------------------------------------------------------------------------- /timegeekbang.com/sanguo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/timegeekbang.com/sanguo.txt -------------------------------------------------------------------------------- /timegeekbang.com/sanguo_v2.py: -------------------------------------------------------------------------------- 1 | import re 2 | def find_item( hero ): 3 | with open('sanguo.txt',encoding='GB18030') as f: 4 | data = f.read().replace('\n','') 5 | name_num = re.findall(hero,data) 6 | # print('主角 %s 出现 %s 次' %(hero, len(name_num))) 7 | 8 | return len(name_num) 9 | 10 | 11 | 12 | 13 | # 读取人物的信息 14 | name_dict = {} 15 | with open('name.txt') as f: 16 | for line in f: 17 | names = line.split('|') 18 | for n in names: 19 | # print(n) 20 | name_num = find_item(n) 21 | name_dict[n] = name_num 22 | 23 | name_sorted = sorted(name_dict.items(), key=lambda item: item[1], reverse=True) 24 | print(name_sorted[0:10]) -------------------------------------------------------------------------------- /timegeekbang.com/sanguo_v3.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def find_main_charecters(charecter_name): 5 | with open('sanguo.txt', encoding='gb18030') as f: 6 | data = f.read().replace("\n", "") 7 | name_num = re.findall(charecter_name, data) 8 | # print('主角 %s 出现了%s 次'%(charecter_name,len(name_num))) 9 | return charecter_name, len(name_num) 10 | 11 | 12 | name_dict = {} 13 | with open('name.txt', encoding='utf-8') as f: 14 | for line in f: 15 | names = line.split('|') 16 | for n in names: 17 | char_name, char_number = find_main_charecters(n) 18 | name_dict[char_name] = char_number 19 | 20 | weapon_dict = {} 21 | with open('weapon.txt', encoding='utf-8') as f: 22 | i = 1 23 | for line in f: 24 | if i%2 == 1: 25 | weapon_name, weapon_number = find_main_charecters(line.strip()) 26 | weapon_dict[weapon_name] = weapon_number 27 | i = i+1 28 | 29 | 30 | name_sorted = sorted(name_dict.items(), key=lambda item: item[1], reverse=True) 31 | print(name_sorted[0:10]) 32 | 33 | weapon_sorted = sorted(weapon_dict.items(), key=lambda item: item[1], reverse=True) 34 | print(weapon_sorted[0:10]) -------------------------------------------------------------------------------- /timegeekbang.com/stdlib_test.py: -------------------------------------------------------------------------------- 1 | # 日常应用比较广泛的模块是: 2 | # 1. 文字处理的 re 3 | # 2. 日期类型的time、datetime 4 | # 3. 数字和数学类型的math、random 5 | # 4. 文件和目录访问的pathlib、os.path 6 | # 5. 数据压缩和归档的tarfile 7 | # 6. 通用操作系统的os、logging、argparse 8 | # 7. 多线程的 threading、queue 9 | # 8. Internet数据处理的 base64 、json、urllib 10 | # 9. 结构化标记处理工具的 html、xml 11 | # 10. 开发工具的unitest 12 | # 11. 调试工具的 timeit 13 | # 12. 软件包发布的venv 14 | # 13. 运行服务的__main__ 15 | 16 | 17 | # . ^ $ * + ? {m} {m,n} [] | \d \D \s () 18 | # ^$ 19 | # .*? 20 | 21 | import re 22 | 23 | 24 | p = re.compile(r'(\d+)-(\d+)-(\d+)') 25 | # print (p.match('aa2018-05-10bb').group(2) ) 26 | # print (p.match('2018-05-10').groups() ) 27 | # 28 | # year, month, day = p.match('2018-05-10').groups() 29 | # print(year) 30 | # 31 | # print (p.search('aa2018-05-10bb')) 32 | # phone = '123-456-789 # 这是电话号码' 33 | # p2 = re.sub(r'#.*$','',phone) 34 | # print(p2) 35 | # p3 = re.sub(r'\D','',p2) 36 | # print(p3) 37 | # findall() 38 | 39 | import random 40 | print( random.randint(1,5)) 41 | print( random.choice(['aa','bb','cc'])) -------------------------------------------------------------------------------- /timegeekbang.com/test1.py: -------------------------------------------------------------------------------- 1 | # 输出一行文字 2 | print('hello time.geerbang!') 3 | 4 | -------------------------------------------------------------------------------- /timegeekbang.com/test_dict.py: -------------------------------------------------------------------------------- 1 | dict1 = {} 2 | print(type(dict1)) 3 | dict2 = { 'x':1 , 'y':2 } 4 | dict2['z'] = 3 5 | 6 | print(dict2) 7 | 8 | -------------------------------------------------------------------------------- /timegeekbang.com/test_for.py: -------------------------------------------------------------------------------- 1 | # 从1 到 10 所有偶数的平方 2 | alist = [] 3 | for i in range(1,11): 4 | if (i % 2 == 0): 5 | alist.append( i*i ) 6 | 7 | 8 | print(alist) 9 | 10 | 11 | blist = [i*i for i in range(1, 11) if(i % 2) == 0] 12 | 13 | print(blist) 14 | 15 | z_num = {} 16 | for i in zodiac_name: 17 | z_num[i] = 0 18 | 19 | z_num = {i:0 for i in zodiac_name} -------------------------------------------------------------------------------- /timegeekbang.com/test_if.py: -------------------------------------------------------------------------------- 1 | x = 'abcd' 2 | if x == 'abc' : 3 | print('x 的值和abc 相等') 4 | else: 5 | print('x和 abc不相等') -------------------------------------------------------------------------------- /timegeekbang.com/thread_test.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | from threading import current_thread 4 | 5 | def myThread(arg1, arg2): 6 | print(current_thread().getName(),'start') 7 | print('%s %s'%(arg1, arg2)) 8 | time.sleep(1) 9 | print(current_thread().getName(),'stop') 10 | 11 | 12 | for i in range(1,6,1): 13 | # t1 = myThread(i, i+1) 14 | t1 = threading.Thread(target=myThread,args=(i, i+1)) 15 | t1.start() 16 | 17 | print(current_thread().getName(),'end') 18 | -------------------------------------------------------------------------------- /timegeekbang.com/thread_testv2.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from threading import current_thread 3 | 4 | class Mythread(threading.Thread): 5 | def run(self): 6 | print(current_thread().getName(),'start') 7 | print('run') 8 | print(current_thread().getName(),'stop') 9 | 10 | 11 | t1 = Mythread() 12 | t1.start() 13 | t1.join() 14 | 15 | print(current_thread().getName(),'end') 16 | -------------------------------------------------------------------------------- /timegeekbang.com/time_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | # print(time.time()) 3 | # print(time.localtime()) 4 | # print(time.strftime('%Y%m%d')) 5 | 6 | 7 | import datetime 8 | print(datetime.datetime.now()) 9 | newtime = datetime.timedelta(minutes=10) 10 | print(datetime.datetime.now()+ newtime) 11 | 12 | one_day=datetime.datetime(2008,5,27) 13 | new_date=datetime.timedelta(days=10) 14 | print( one_day + new_date) -------------------------------------------------------------------------------- /timegeekbang.com/weapon.txt: -------------------------------------------------------------------------------- 1 | 青龍偃月刀 2 | 3 | 丈八點鋼矛 4 | 5 | 鐵脊蛇矛 6 | 7 | 涯角槍 8 | 9 | 諸葛槍 10 | 11 | 方天畫戟 12 | 13 | 長柄鐵錘 14 | 15 | 鐵蒺藜骨朵 16 | 17 | 大斧 18 | 19 | 蘸金斧 20 | 21 | 三尖刀 22 | 23 | 截頭大刀 24 | 25 | 馬岱寶刀 26 | 27 | 古錠刀 28 | 29 | 衠鋼槊 30 | 31 | 丈八長標 32 | 33 | 王雙大刀 34 | 35 | 呂虔刀 36 | 37 | 龍泉劍 38 | 39 | 倚天劍 40 | 41 | 青釭 42 | 43 | 七寶刀 44 | 45 | 雙股劍 46 | 47 | 松紋廂寶劍 48 | 49 | 孟德劍 50 | 51 | 思召劍 52 | 53 | 飛景三劍 54 | 55 | 文士劍 56 | 57 | 蜀八劍 58 | 59 | 鎮山劍 60 | 61 | 吳六劍 62 | 63 | 皇帝吳王劍 64 | 65 | 日月刀 66 | 67 | 百辟寶刀 68 | 69 | 龍鱗刀 70 | 71 | 百辟匕首二 72 | 73 | 鐵鞭 74 | 75 | 鋼鞭 76 | 77 | 四楞鐵簡 78 | 79 | 雙鐵戟 80 | 81 | 諸葛連弩 82 | 83 | 寶雕弓 84 | 85 | 鵲畫弓 86 | 87 | 虎筋弦弓 88 | 89 | 兩石力之弓 90 | 91 | 手戟 92 | 93 | 短戟 94 | 95 | 飛石 96 | 97 | 流星錘 98 | 99 | 銅撾 100 | -------------------------------------------------------------------------------- /timegeekbang.com/with_test.py: -------------------------------------------------------------------------------- 1 | class Testwith(object): 2 | ''' 3 | with 包含了 __enter__ 和 __exit__ 方法 4 | ''' 5 | 6 | def __enter__(self): 7 | print('run now ') 8 | 9 | def __exit__(self, exc_type, exc_val, exc_tb): 10 | if exc_tb is None: 11 | print('exit normal ') 12 | else: 13 | print('exit with exception') 14 | 15 | 16 | with Testwith(): 17 | print('test') 18 | raise NameError('Exception') -------------------------------------------------------------------------------- /timegeekbang.com/zodiac.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | # zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | # u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | # zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | # (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | # 8 | # 9 | # (month, day) = (2, 15) 10 | # 11 | # zodiac_day = filter(lambda x: x<=(month, day), zodiac_days) 12 | # # print(zodiac_day) 13 | # 14 | # zodac_len = len(list(zodiac_day)) % 12 15 | # print(zodiac_name[zodac_len]) 16 | 17 | a_list = ['abc', 'xyz'] 18 | a_list.append('X') 19 | print (a_list) 20 | a_list.remove('xyz') 21 | print(a_list) 22 | 23 | -------------------------------------------------------------------------------- /timegeekbang.com/zodiac_v2.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | 8 | 9 | # 用户输入月份和日期 10 | int_month = int(input('请输入月份:')) 11 | int_day = int(input('请输入日期')) 12 | 13 | # for zd_num in range(len(zodiac_days)): 14 | # if zodiac_days[zd_num] >= (int_month, int_day): 15 | # print(zodiac_name[zd_num]) 16 | # break 17 | # elif int_month == 12 and int_day >23: 18 | # print(zodiac_name[0]) 19 | # break 20 | 21 | n = 0 22 | while zodiac_days[n] < (int_month,int_day): 23 | if int_month == 12 and int_day >23: 24 | break 25 | n += 1 26 | 27 | print(zodiac_name[n]) 28 | 29 | 30 | 31 | 32 | # print(type(str_month)) 33 | # 34 | # zodiac_day = filter(lambda x: x<=(month, day), zodiac_days) 35 | # # print(zodiac_day) 36 | # 37 | # zodac_len = len(list(zodiac_day)) % 12 38 | # print(zodiac_name[zodac_len]) 39 | 40 | -------------------------------------------------------------------------------- /timegeekbang.com/zodiac_v3.py: -------------------------------------------------------------------------------- 1 | 2 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 3 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 4 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 5 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 6 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 7 | 8 | 9 | cz_num = {} 10 | for i in chinese_zodiac: 11 | cz_num[i] = 0 12 | 13 | z_num = {} 14 | for i in zodiac_name: 15 | z_num[i] = 0 16 | 17 | 18 | 19 | 20 | while True: 21 | 22 | # 用户输入出生年份月份和日期 23 | year = int(input('请输入年份:')) 24 | month = int(input('请输入月份:')) 25 | day = int(input('请输入日期:')) 26 | 27 | 28 | n = 0 29 | while zodiac_days[n] < (month,day): 30 | if month == 12 and day >23: 31 | break 32 | n += 1 33 | # 输出生肖和星座 34 | print(zodiac_name[n]) 35 | 36 | 37 | print('%s 年的生肖是 %s' % (year, chinese_zodiac[year % 12])) 38 | 39 | cz_num[chinese_zodiac[year % 12]] += 1 40 | z_num[zodiac_name[n]] += 1 41 | 42 | # 输出生肖和星座的统计信息 43 | for each_key in cz_num.keys(): 44 | print('生肖 %s 有 %d 个'%(each_key,cz_num[each_key])) 45 | 46 | for each_key in z_num.keys(): 47 | print('星座 %s 有 %d 个' %(each_key,z_num[each_key])) 48 | 49 | 50 | -------------------------------------------------------------------------------- /txt/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /txt/name.txt: -------------------------------------------------------------------------------- 1 | 諸葛亮|關羽|劉備|曹操|孫權|關羽|張飛|呂布|周瑜|趙雲|龐統|司馬懿|黃忠|馬超 -------------------------------------------------------------------------------- /txt/sanguo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/txt/sanguo.txt -------------------------------------------------------------------------------- /txt/weapon.txt: -------------------------------------------------------------------------------- 1 | 青龍偃月刀 2 | 3 | 丈八點鋼矛 4 | 5 | 鐵脊蛇矛 6 | 7 | 涯角槍 8 | 9 | 諸葛槍 10 | 11 | 方天畫戟 12 | 13 | 長柄鐵錘 14 | 15 | 鐵蒺藜骨朵 16 | 17 | 大斧 18 | 19 | 蘸金斧 20 | 21 | 三尖刀 22 | 23 | 截頭大刀 24 | 25 | 馬岱寶刀 26 | 27 | 古錠刀 28 | 29 | 衠鋼槊 30 | 31 | 丈八長標 32 | 33 | 王雙大刀 34 | 35 | 呂虔刀 36 | 37 | 龍泉劍 38 | 39 | 倚天劍 40 | 41 | 青釭 42 | 43 | 七寶刀 44 | 45 | 雙股劍 46 | 47 | 松紋廂寶劍 48 | 49 | 孟德劍 50 | 51 | 思召劍 52 | 53 | 飛景三劍 54 | 55 | 文士劍 56 | 57 | 蜀八劍 58 | 59 | 鎮山劍 60 | 61 | 吳六劍 62 | 63 | 皇帝吳王劍 64 | 65 | 日月刀 66 | 67 | 百辟寶刀 68 | 69 | 龍鱗刀 70 | 71 | 百辟匕首二 72 | 73 | 鐵鞭 74 | 75 | 鋼鞭 76 | 77 | 四楞鐵簡 78 | 79 | 雙鐵戟 80 | 81 | 諸葛連弩 82 | 83 | 寶雕弓 84 | 85 | 鵲畫弓 86 | 87 | 虎筋弦弓 88 | 89 | 兩石力之弓 90 | 91 | 手戟 92 | 93 | 短戟 94 | 95 | 飛石 96 | 97 | 流星錘 98 | 99 | 銅撾 100 | -------------------------------------------------------------------------------- /在Windows系统上安装Python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/在Windows系统上安装Python.pdf -------------------------------------------------------------------------------- /零基础学Python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wilsonyin123/geekbangpython/135f78d440de8d34bc81630fd4200f43c8dc003d/零基础学Python.pdf --------------------------------------------------------------------------------