D05——C语言基础学PYTHON
C语言基础学习PYTHON——基础学习D05
20180815内容纲要:
1 模块
2 包
3 import的本质
4 内置模块详解
(1)time&datetime
(2)datetime
(3)random
(4)os
(5)sys
(6)json&pickle
(7)shelve
(8)xml
(9)shutil
(10)PyYaml
(11)configpaser
(12)hashlib
(13)re
5 练习:开发一个简单的python计算器(挑战性很强)
1 模块
模块:
>>>定义:本质就是.py结尾的PYTHON文件,用来从逻辑上组织python代码(变量、函数、类、逻辑),实现一个功能。
>>>导入方法:
1 import module_name 调用module_name.xxx 2 from module_name import * 直接调用即可(导入优化) 3 from module_name import func_module_name as func 4 form . improt module_name 从当前目录下导入module_name
导入方法
>>>模块分类
- 自定义模块
- 内置标准模块(又称标准库)
- 开源模块
自定义模块和开源模块的使用参考 http://www.cnblogs.com/wupeiqi/articles/4963027.html
2 包
包:用来从逻辑上组织模块,本质就是一个目录,(必须带有一个__init__.py文件),
那么在导入包之后改如何调用包下面的.py文件呢?
1 #Author:ZhangKanghui 2 print("我最美") 3 from . import foo
__init__.py
1 #Author:ZhangKanghui 2 def foo(): 3 print("我喜欢你")
foo.py
1 #Author:ZhangKanghui 2 import package 3 4 package.foo.foo()
调用(必须与包在同级目录下)
3 import的本质
import的本质(路径搜索和搜索路径):
>>>导入模块的本质就是把python文件解释一遍
>>>导入包的本质就是执行包下的__inint__.py文件
在导入的过程中,要确保存储路径在同级目录下。如果不在那怎么解决呢?
1 #Author:ZhangKanghui 2 3 import package#直接运行 4 5 import sys 6 print(sys.path) #获取当前文件的存储位置 7 8 import os 9 print(os.path.abspath(__file__)) #获取当前文件的存储路径 10 print(os.path.dirname(os.path.abspath(__file__))) 11 12 #添加路径: 13 sys.path.append() #追加到sys.path的最后,如果想放到前面怎么办 14 sys.path.insert() 15 16 #os、sys模块下面有详解
访问目录
4 内置模块详解
(1)time
首先,在python中有这么几种表示时间的方法:
(1)时间戳
(2)元组(struct_time)共有九个元素:年,月,日,小时,分钟,秒,一周的第几天,一年的第几天,时区
(3)格式化的时间字符串
1 >>> import time 2 >>> time.time() 3 1534000340.4254425 #这是从1970年开始计算至今的秒数。 4 #这是命令行操作 5
时间戳time.time()
1 >>> time.localtime() 2 time.struct_time(tm_year=2018, tm_mon=8, tm_mday=11, tm_hour=23, tm_min=17, tm_sec=19, tm_wday=5, tm_yday=223, tm_isdst=0)
元组 localtime()
1 x =time.localtime() 2 >>> x 3 time.struct_time(tm_year=2018, tm_mon=8, tm_mday=12, tm_hour=0, tm_min=0, tm_sec=43, tm_wday=6, tm_yday=224, tm_isdst=0) 4 >>> time.strftime("%Y-%m-%d %H:%m:%S",x) 5 \'2018-08-12 00:08:43\'
格式化的时间字符串time.strftime()
科普:
>>>UTC(Coordinated Universal Time,世界协调时)即格林威治天文时间,世界标准时间。在中国为UTC+8,
>>>DST(Daylight Saving Time)即夏令时
在补充一点格式:
>>>comomly used format code:
1 %Y Year with century as a decimal number. 2 %m Month as a decimal number [01,12]. 3 %d Day of the month as a decimal number [01,31]. 4 %H Hour (24-hour clock) as a decimal number [00,23]. 5 %M Minute as a decimal number [00,59]. 6 %S Second as a decimal number [00,61]. 7 %z Time zone offset from UTC. 8 %a Locale\'s abbreviated weekday name. 9 %A Locale\'s full weekday name. 10 %b Locale\'s abbreviated month name. 11 %B Locale\'s full month name. 12 %c Locale\'s appropriate date and time representation. 13 %I Hour (12-hour clock) as a decimal number [01,12]. 14 %p Locale\'s equivalent of either AM or PM.
commmonly used format code
a time.localtime() 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。
b time.gmtime() 将一个时间戳转换为UTC时区(0时区)的struct_time。
>>> time.localtime() time.struct_time(tm_year=2018, tm_mon=8, tm_mday=15, tm_hour=10, tm_min=3, tm_sec=22, tm_wday=2, tm_yday=227, tm_isdst=0) >>> time.gmtime() time.struct_time(tm_year=2018, tm_mon=8, tm_mday=15, tm_hour=2, tm_min=3, tm_sec=30, tm_wday=2, tm_yday=227, tm_isdst=0) #这也验证了中国时区是UTC+8
二者有什么区别呢?
c time.mktime() 将一个struct_time转化为时间戳
1 >>> x =time.localtime() 2 >>> x 3 time.struct_time(tm_year=2018, tm_mon=8, tm_mday=15, tm_hour=10, tm_min=7, tm_sec=30, tm_wday=2, tm_yday=227, tm_isdst=0) 4 >>> time.mktime(x) 5 1534298850.0
time.mktime()
d time.strftime(format[,t])
1 >>>import time 2 >>> x =time.localtime() 3 >>> x 4 time.struct_time(tm_year=2018, tm_mon=8, tm_mday=15, tm_hour=10, tm_min=13, tm_sec=47, tm_wday=2, tm_yday=227, tm_isdst=0) 5 >>> time.strftime("%Y-%m-%d %H:%m:%S",x) 6 \'2018-08-15 10:08:47\'
time.strftime()
e time.strptime([格式化时间, format]) 把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
1 >>>import time 2 >>>time.strptime(\'2011-05-05 16:37:06\', \'%Y-%m-%d %X\') 3 time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1)
time.strptime([格式化时间,format])
f asctime([t]) 把一个表示时间的元组或者struct_time表示为这种形式:\’Sun Jun 20 23:21:05 1993\’。如果没有参数,将会将time.localtime()作为参数传入。
g ctime([seconds]) 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。
1 >>> time.asctime() 2 \'Sun Aug 12 23:27:28 2018\' 3 >>> time.ctime() 4 \'Sun Aug 12 23:52:40 2018\' 5 #不要忘记导入time模块哟
一起来看看
接下来上图~
(2)datetime
a datetime.datetime.now()
1 >>> import datetime 2 >>> datetime.datetime.now() 3 datetime.datetime(2018, 8, 12, 23, 54, 0, 324086)
datetime.datetime.now()
b datetime.date.fromtimestamp(time.time()) 时间戳直接转成日期格式
1 >>> datetime.date.fromtimestamp(time.time()) 2 datetime.date(2018, 8, 12)
时间戳
1 >>> datetime.datetime.now() + datetime.timedelta(3) 2 datetime.datetime(2018, 8, 15, 23, 55, 31, 676392)
当前时间+3天
1 >>> datetime.datetime.now() + datetime.timedelta(-3) 2 datetime.datetime(2018, 8, 9, 23, 55, 57, 20937)
当前时间-3天
1 >>> datetime.datetime.now() + datetime.timedelta(hours=3) 2 datetime.datetime(2018, 8, 13, 2, 56, 25, 388509)
当前时间+3小时
1 >>> datetime.datetime.now() + datetime.timedelta(minutes=30) 2 datetime.datetime(2018, 8, 13, 0, 26, 53, 300279)
当前时间+30分
(3)random
1 #random.random() 生成一个0-1的随机浮点数 2 >>> random.random() 3 0.6813665412962242 4 #那么能不能指定范围呢? 5 #random.uniform(a,b) 6 >>> random.uniform(2,5) 7 3.7103054399886606 8 #random.randint(a,b) 用于生成一个指定范围内的整数,包括a,b 9 >>> random.randint(1,3) 10 3 11 >>> random.randint(1,3) 12 3 13 >>> random.randint(1,3) 14 1 15 #random.randrange(start,stop,step) 从指定范围获得一个随机数,但不包括stop 16 >>> random.randrange(1,3) 17 2 18 >>> random.randrange(1,3) 19 1 20 #random.choice("序列") 从序列中获取一个随机元素 21 >>> random.choice(\'hello\') 22 \'e\' 23 >>> random.choice(\'hello\') 24 \'o\' 25 >>> random.choice(\'hello\') 26 \'o\' 27 >>> random.choice(\'hello\') 28 \'o\' 29 >>> random.choice(\'hello\') 30 \'e\' 31 #random.sample("序列",k) 从序列中获取k个随机元素,必须指定k 32 >>> random.sample(\'hello\',2) 33 [\'l\', \'h\'] 34 >>> random.sample(\'hello\',2) 35 [\'h\', \'o\'] 36 >>> random.sample(\'hello\',2) 37 [\'h\', \'o\'] 38 random.shuffle() 洗牌 39 >>> l =[1,2,3,4,5,6] 40 >>> import random 41 >>> random.shuffle(l) 42 >>> l 43 [4, 6, 3, 2, 1, 5]
random模块
(2)os模块
os模块是与操作系统交互的一个接口
a os.getcwd() 获取当前工作目录
b os.chdir() 改变工作目录
1 os.getcwd() 2 \'C:\\Users\\miraacle\' 3 >>> os.chdir(\'C:\\Users\') 4 >>> os.getcwd() 5 \'C:\\Users\' 6 >>> os.chdir(r"C:\Users\miraacle") #对比上一条chdir命令有什么区别/ 7 >>> os.getcwd() 8 \'C:\\Users\\miraacle\'
如何操作
c os.curdir() 返回当前目录
d os.pardir() 返回当前目录的上一级目录
1 >>> os.curdir 2 \'.\' 3 >>> os.pardir 4 \'..\'
看操作
d os.makedirs(r”C:\a\b\c\d”) 生成多层递归目录
e os.removesdirs(r”C:\a\b\c\d”) 若目录为空,则删除,并递归到上一级目录,若也为空则删除,以此类推。
f os.mkdir() 生成单级目录
g os.rmdir() 删除单级目录
h os.listdir()
1 >>> os.listdir(\'.\') 2 [\'.android\', \'.astropy\', \'.conda\', \'.ipython\', \'.matplotlib\', \'.oracle_jre_usage\', \'.Origin\', \'.PyCharm2017.1\', \'.QtWebEngineProcess\',\'3D Objects\', \'Anaconda3\', \'AppData\', \'Application Data\', \'Contacts\', \'Cookies\', \'Desktop\', \'Documents\', \'Downloads\', \'Evernote\', \'Favorites\', \'IntelGraphicsProfiles\', \'Links\', \'Local Settings\', \'LocalStorage\', \'MicrosoftEdgeBackups\', \'Music\', \'My Documents\', \'NetHood\', \'NTUSER.DAT\', \'ntuser.dat.LOG1\', \'ntuser.dat.LOG2\', \'NTUSER.DAT{2fe3e105-6421-11e8-b183-74e6e23ee3d1}.TM.blf\', \'NTUSER.DAT{2fe3e105-6421-11e8-b18374e6e23ee3d1}.TMContainer00000000000000000001.regtrans-ms\', \'NTUSER.DAT{2fe3e105-6421-11e8-b183-74e6e23ee3d1}.TMContainer00000000000000000002.regtrans-ms\', \'ntuser.ini\', \'OneDrive\', \'OneDrive.old\', \'Pictures\', \'PrintHood\', \'PyCharm 2017.1.2\', \'PycharmProjects\',\'Recent\', \'Saved Games\', \'Searches\', \'SendTo\', \'Templates\', \'Videos\', \'WebpageIcons.db\', \'「开始」菜单\', \'微博图片\', \'新建文件夹\']
一堆东西
1 >>> os.listdir(\'..\') 2 [\'Administrator\', \'All Users\', \'Default\', \'Default User\', \'Default.migrated\', \'desktop.ini\', \'miraacle\', \'Public\']
这就清楚多了
i os.remove() 删除一个文件
j os.rename(\’oldname\’,\’newname\’)
k os.stat(\’path\’) 详细信息属性
1 >>> os.stat(\'微博图片\') 2 os.stat_result(st_mode=16895, st_ino=5910974511128476, st_dev=43069414, st_nlink=1, st_uid=0, st_gid=0, st_size=0, 3 st_atime=1481191549, st_mtime=1481191549, st_ctime=1462148410)
详细属性
l os.sep 输出操作系统特定的路径分隔符
m os.linesep 输出当前平台使用的行终止符 dd
n os.pathsep 输出用于分割文件路径的字符串
o os.name 输出字符串当前使用的平台
>>> os.sep \'\\\' >>> os.linesep \'\r\n\' >>> os.pathsep \';\' >>> os.name \'nt\'
操作集锦
p os.environ 获取系统环境变量
1 >>> os.environ 2 environ({\'ACTEL_FOR_ALTIUM_OVERRIDE\': \' \', \'ALLUSERSPROFILE\': \'C:\\ProgramData\', \'ALTERA_FOR_ALTIUM_OVERRIDE\': \' \', \'ALTIUMPATH\': \'C:\\Program Files (x86)\\Altium2004 SP2\\System\', \'APPDATA\': \'C:\\Users\\miraacle\\AppData\\Roaming\', 3 \'CM2015DIR\': \'C:\\Program Files (x86)\\Common Files\\Autodesk Shared\\Materials\\\', \'COMMONPROGRAMFILES\': 4 \'C:\\Program Files (x86)\\Common Files\', \'COMMONPROGRAMFILES(X86)\': \'C:\\Program Files (x86)\\Common Files\', 5 \'COMMONPROGRAMW6432\': \'C:\\Program Files\\Common Files\', \'COMPUTERNAME\': \'MIRACLE\', \'COMSPEC\': \'C:\\WINDOWS\\system32\\cmd.exe\', 6 \'DRIVERDATA\': \'C:\\Windows\\System32\\Drivers\\DriverData\', \'FPS_BROWSER_APP_PROFILE_STRING\': \'Internet Explorer\', 7 \'FPS_BROWSER_USER_PROFILE_STRING\': \'Default\', \'HOMEDRIVE\': \'C:\', \'HOMEPATH\': \'\\Users\\miraacle\', \'LOCALAPPDATA\': 8 \'C:\\Users\\miraacle\\AppData\\Local\', \'LOGONSERVER\': \'\\\\MIRACLE\', \'NUMBER_OF_PROCESSORS\': \'4\', \'ONEDRIVE\': 9 \'C:\\Users\\miraacle\\OneDrive\', \'OS\': \'Windows_NT\', \'PATH\': \'C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files\\WIDCOMM\\Bluetooth Software\\;C:\\Program Files\\WIDCOMM\\BluetoothSoftware\\syswow64;;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files (x86)\\Altium2004 SP2\\System;C:\\Users\\miraacle\\AppData\\Local\\Programs\\Python\\Python36-32\\Scripts\\; 10 C:\\Users\\miraacle\\AppData\\Local\\Programs\\Python\\Python36-32\\;C:\\Users\\miraacle\\Anaconda3; 11 C:\\Users\\miraacle\\Anaconda3\\Scripts;C:\\Users\\miraacle\\Anaconda3\\Library\\bin; 12 C:\\Users\\miraacle\\AppData\\Local\\Microsoft\\WindowsApps;\', \'PATHEXT\': \'.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC\', 13 \'PROCESSOR_ARCHITECTURE\': \'x86\', \'PROCESSOR_ARCHITEW6432\': \'AMD64\', \'PROCESSOR_IDENTIFIER\': \'Intel64 Family 6 Model 61 Stepping 4, 14 GenuineIntel\', \'PROCESSOR_LEVEL\': \'6\', \'PROCESSOR_REVISION\': \'3d04\', \'PROGRAMDATA\': \'C:\\ProgramData\', \'PROGRAMFILES\': 15 \'C:\\Program Files (x86)\', \'PROGRAMFILES(X86)\': \'C:\\Program Files (x86)\', \'PROGRAMW6432\': \'C:\\Program Files\', \'PROMPT\': 16 \'$P$G\', \'PSMODULEPATH\': \'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\', 17 \'PUBLIC\': \'C:\\Users\\Public\', \'SESSIONNAME\': \'Console\', \'SYNAPROGDIR\': \'Synaptics\\SynTP\', \'SYSTEMDRIVE\': \'C:\', \'SYSTEMROOT\': 18 \'C:\\WINDOWS\', \'TEMP\': \'C:\\Users\\miraacle\\AppData\\Local\\Temp\', \'TMP\': \'C:\\Users\\miraacle\\AppData\\Local\\Temp\', 19 \'USERDOMAIN\': \'MIRACLE\', \'USERDOMAIN_ROAMINGPROFILE\': \'MIRACLE\', \'USERNAME\': \'miraacle\', \'USERPROFILE\': \'C:\\Users\\miraacle\', 20 \'WINDIR\': \'C:\\WINDOWS\'})
可怕的环境变量
q os.system()
1 >>> os.system(\'dir\') 2 驱动器 C 中的卷是 我的磁盘 3 卷的序列号是 0291-2FE6 4 5 C:\Users\miraacle 的目录 6 7 2018/08/10 00:17 <DIR> . 8 2018/08/10 00:17 <DIR> .. 9 2015/05/10 21:32 <DIR> .android 10 2018/07/04 22:40 <DIR> .astropy 11 2018/07/23 01:27 <DIR> .conda 12 2018/07/04 22:38 <DIR> .ipython 13 2018/07/04 22:51 <DIR> .matplotlib 14 2016/11/23 22:45 <DIR> .oracle_jre_usage 15 2017/01/17 22:43 <DIR> .Origin 16 2018/06/17 00:53 <DIR> .PyCharm2017.1 17 2017/01/17 22:43 <DIR> .QtWebEngineProcess 18 2018/07/18 17:47 <DIR> 3D Objects 19 2018/08/13 10:23 <DIR> Anaconda3 20 2018/07/18 17:47 <DIR> Contacts 21 2018/08/13 14:04 <DIR> Desktop 22 2018/07/18 17:47 <DIR> Documents 23 2018/08/12 23:49 <DIR> Downloads 24 2016/10/21 18:36 <DIR> Evernote 25 2018/07/18 17:47 <DIR> Favorites 26 2018/07/18 17:47 <DIR> Links 27 2017/01/15 16:13 <DIR> LocalStorage 28 2018/07/18 17:47 <DIR> Music 29 2018/04/05 01:08 <DIR> OneDrive 30 2015/05/21 18:28 <DIR> OneDrive.old 31 2018/07/18 17:47 <DIR> Pictures 32 2018/06/17 00:50 <DIR> PyCharm 2017.1.2 33 2018/07/04 23:11 <DIR> PycharmProjects 34 2018/07/18 17:47 <DIR> Saved Games 35 2018/07/18 17:47 <DIR> Searches 36 2018/07/18 17:47 <DIR> Videos 37 2017/06/14 00:26 22,528 WebpageIcons.db 38 2016/12/08 18:05 <DIR> 微博图片 39 2017/05/04 09:33 <DIR> 新建文件夹 40 1 个文件 22,528 字节 41 32 个目录 43,556,442,112 可用字节 42 0
看看系统
1 >>> os.system(\'ipconfig/all\') 2 3 Windows IP 配置 4 5 主机名 . . . . . . . . . . . . . : miracle 6 主 DNS 后缀 . . . . . . . . . . . : 7 节点类型 . . . . . . . . . . . . : 混合 8 IP 路由已启用 . . . . . . . . . . : 否 9 WINS 代理已启用 . . . . . . . . . : 否 10 11 以太网适配器 以太网: 12 13 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 14 连接特定的 DNS 后缀 . . . . . . . : 15 描述. . . . . . . . . . . . . . . : Realtek PCIe FE Family Controller 16 物理地址. . . . . . . . . . . . . : 74-E6-E2-3E-E3-D1 17 DHCP 已启用 . . . . . . . . . . . : 是 18 自动配置已启用. . . . . . . . . . : 是 19 20 无线局域网适配器 本地连接* 2: 21 22 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 23 连接特定的 DNS 后缀 . . . . . . . : 24 描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter 25 物理地址. . . . . . . . . . . . . : 2E-33-7A-FC-F0-B5 26 DHCP 已启用 . . . . . . . . . . . : 是 27 自动配置已启用. . . . . . . . . . : 是 28 29 无线局域网适配器 本地连接* 4: 30 31 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 32 连接特定的 DNS 后缀 . . . . . . . : 33 描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter #3 34 物理地址. . . . . . . . . . . . . : 2E-33-7A-FC-F8-B5 35 DHCP 已启用 . . . . . . . . . . . : 是 36 自动配置已启用. . . . . . . . . . : 是 37 38 无线局域网适配器 WLAN: 39 40 连接特定的 DNS 后缀 . . . . . . . : 41 描述. . . . . . . . . . . . . . . : Dell Wireless 1704 802.11b/g/n (2.4GHz) 42 物理地址. . . . . . . . . . . . . : 2C-33-7A-FC-F0-B5 43 DHCP 已启用 . . . . . . . . . . . : 是 44 自动配置已启用. . . . . . . . . . : 是 45 IPv6 地址 . . . . . . . . . . . . : 2001:250:20a:1900:1c19:8fdc:c570:89f6(首选) 46 临时 IPv6 地址. . . . . . . . . . : 2001:250:20a:1900:5d56:4217:aa5a:e812(首选) 47 本地链接 IPv6 地址. . . . . . . . : fe80::1c19:8fdc:c570:89f6%3(首选) 48 IPv4 地址 . . . . . . . . . . . . : 10.20.72.135(首选) 49 子网掩码 . . . . . . . . . . . . : 255.255.224.0 50 获得租约的时间 . . . . . . . . . : 2018年8月13日 9:30:01 51 租约过期的时间 . . . . . . . . . : 2018年8月13日 14:58:54 52 默认网关. . . . . . . . . . . . . : fe80::276:86ff:febe:7a41%3 53 10.20.95.254 54 DHCP 服务器 . . . . . . . . . . . : 10.100.100.100 55 DHCPv6 IAID . . . . . . . . . . . : 36451194 56 DHCPv6 客户端 DUID . . . . . . . : 00-01-00-01-1E-59-AF-DE-74-E6-E2-3E-E3-D1 57 DNS 服务器 . . . . . . . . . . . : 202.112.209.122 58 202.112.209.123 59 TCPIP 上的 NetBIOS . . . . . . . : 已启用 60 0
看看ip配置
r os.path.xxx
1 os.path.abspath() 获取某一文件的绝对路径 2 os.path.split(path) 分割路径 3 os.path.diranme(path) 返回path的目录,其实就是os.path.split()的第一个元素 4 os.path.basename(path) 返回path的最后一个文件名 5 os.path.exists(path) 判断路径是否存在 6 os.path.isabs(path) 判断是否为绝对路径 7 os.path.isfile(path) 判断是否为文件 8 os.path.isdir(path) 判断是否为目录 9 os.path.join() 将说个路径组合返回 10 os.path.getatime(path) 返回path所指向的文件或目录的最后存储时间 11 so.path.getmtime(path) 返回path所指向的文件或目录的最后修改时间
关于os.path.xxx
终于完了~
(5)sys模块
a sys.version 获取python解释器的版本信息
b sys.platform 获取操作系统平台名称
c sys.argv 命令行参数list,第一个元素是程序本身路径
d sys.path 返回模块的搜索路径,初始化时使用python环境变量的值
e sys.exit(n) 退出程序,正常退出时exit(0)
>>> sys.version \'3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)]\' >>> sys.platform \'win32\' >>>C:\Users\miraacle\PycharmProjects\s\day5>module_sys.py 1 2 3 4 5 [\'C:\\Users\\miraacle\\PycharmProjects\\s\\day5\\module_sys.py\', \'1\', \'2\', \'3\', \'4\', \'5\']
sys模块操作
(6)json&pickle模块
json把字符串、列表、字典等各语言通用的数据类型写进文件里。便于各平台和语言之前进行数据交互。
pickle,用于python特有的类型和python的数据类型间进行转换。
1 #Author:ZhangKanghui 2 import json 3 4 info ={ 5 \'name\':\'Kanghui\', 6 \'age\':23 7 } 8 #强行转成字符串,不推荐使用。因为反序列化不好办。 9 \'\'\' 10 f =open(\'文本.txt\',\'w\') 11 #f.write(info) #TypeError: write() argument must be str, not dict 12 f.write(str(info)) 13 f.close() 14 \'\'\' 15 #推荐使用json.dumps或者dump 16 f =open(\'文本.txt\',\'w\') 17 f.write( json.dumps(info) ) #等价于json.dump(info,f) 18 f.close()
json序列化
1 #Author:ZhangKanghui 2 3 import json 4 #json只能处理简单的数据类型,例如字典,列表字符串。json在所有语言之间都一样。因为不同语言进行数据交互,能够使用不同语言。 5 #xml用于在不同语言之间进行数据交互,在不断地被json取代,主流的在不同平台和语言之间数据交互。因为跨语言,所以不能处理复杂的 6 7 f =open(\'文本.txt\',\'r\') 8 #f.write(info) TypeError: write() argument must be str, not dict 9 # data =f.read() 10 # f.close() 11 # print(data) 12 #print(data["age"]) 此时TypeError: string indices must be integers因为是字符串,现在需要变回字典 13 #那怎么办呢? 14 \'\'\' 15 data =eval( f.read() ) 16 f.close() 17 print(data["age"]) 18 \'\'\' 19 #不用eval呢?eval不是一个通用的 20 data =json.loads(f.read()) 21 print(data["age"])
json反序列化
1 #Author:ZhangKanghui 2 import pickle 3 date ={"k1":123,"k2":\'hello\'} 4 #pickle.dumps 将数据通过特殊形式转换为只有python语言认识的字符串 5 p_str =pickle.dumps(data) 6 print(p_str) 7 8 #pickle.dump 将数据通过特殊形式转换为只有python语言认识的字符串,并写入文件 9 with open(\'pickle序列化文本.txt\',\'w\') as f: 10 pickle.dump(date,f)
pickle序列化
1 #Author:ZhangKanghui 2 #pickle和json的用法几乎完全一样 3 import pickle 4 5 def sayhi(name): 6 print("hello",name) 7 info ={ 8 \'name\':\'Kanghui\', 9 \'age\':23, 10 \'func\':sayhi 11 } 12 f =open(\'文本.txt\',\'wb\') 13 f.write( pickle.dump(info) ) 14 f.close()
可以dump不一样可以load
pickle的用于与json完全一样。
(7)shelve模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。
1 #Author:ZhangKanghui 2 3 import shelve 4 import datetime 5 d =shelve.open("text.txt",\'w\') #打开一个文件 6 \'\'\' 7 info ={"age":23,"job":\'std\'} 8 name =["a","b"] 9 d[\'name\']=name #持久化列表 10 d[\'info\']=info #持久化字典 11 d["date"]=datetime.datetime.now() 12 d.close() 13 \'\'\' 14 print(d.get("name")) 15 print(d.get("info")) 16 print(d.get("date"))
shelve模块
运行的结果会生成三个文件:text.txt.bak、text.txt.dir,text.txt.dat。貌似很好用的样子~
(8)xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单。
xml的格式如下,就是通过<>节点来区别数据结构的:
1 <?xml version="1.0"?> 2 <data> 3 <country name="Liechtenstein"> 4 <rank updated="yes">2</rank> 5 <year>2008</year> 6 <gdppc>141100</gdppc> 7 <neighbor name="Austria" direction="E"/> 8 <neighbor name="Switzerland" direction="W"/> 9 </country> 10 <country name="Singapore"> 11 <rank updated="yes">5</rank> 12 <year>2011</year> 13 <gdppc>59900</gdppc> 14 <neighbor name="Malaysia" direction="N"/> 15 </country> 16 <country name="Panama"> 17 <rank updated="yes">69</rank> 18 <year>2011</year> 19 <gdppc>13600</gdppc> 20 <neighbor name="Costa Rica" direction="W"/> 21 <neighbor name="Colombia" direction="E"/> 22 </country> 23 </data>
xml格式
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 print(root.tag) 6 7 #遍历xml文档 8 for child in root: 9 print(child.tag, child.attrib) 10 for i in child: 11 print(i.tag,i.text)
遍历xml文档
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 print(root.tag) 6 #只遍历year 节点 7 for node in root.iter(\'year\'): 8 print(node.tag,node.text)
只遍历节点
还可以修改和删除xml文档:
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 6 #修改 7 for node in root.iter(\'year\'): 8 new_year = int(node.text) + 1 9 node.text = str(new_year) 10 node.set("updated","yes") 11 12 tree.write("xmltest.xml") 13 14 15 #删除node 16 for country in root.findall(\'country\'): 17 rank = int(country.find(\'rank\').text) 18 if rank > 50: 19 root.remove(country) 20 21 tree.write(\'output.xml\')
xml修改和删除
还可以自行创建xml文档
1 import xml.etree.ElementTree as ET 2 3 4 new_xml = ET.Element("namelist") 5 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) 6 age = ET.SubElement(name,"age",attrib={"checked":"no"}) 7 sex = ET.SubElement(name,"sex") 8 sex.text = \'33\' 9 name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) 10 age = ET.SubElement(name2,"age") 11 age.text = \'19\' 12 13 et = ET.ElementTree(new_xml) #生成文档对象 14 et.write("test.xml", encoding="utf-8",xml_declaration=True) 15 16 ET.dump(new_xml) #打印生成的格式
xml文档创建
(9)shutil模块
高级的 文件、文件夹、压缩包 处理模块。
1 #Author:ZhangKanghui 2 #将一个文件拷贝到另一个文件中 3 import shutil 4 shutil.copyfileobj(open(\'old xml\',\'r\'),open(\'new xml\',\'w\')) 5 6 #拷贝文件和权限 7 shutil.copy(\'f1.log\',\'f2.log\') #目标文件无需存在 8 9 #shutil.copy2(src, dst)拷贝文件和状态信息 10 shutil.copy2(\'f1.log\', \'f2.log\') 11 12 #仅拷贝权限。内容、组、用户均不变。 13 shutil.copymode(\'f1.log\',\'f2.log\') #目标文件必须存在 14 15 #仅拷贝文件的状态信息,包括:mode bits, atime, mtime, flags 16 shutil.copystat(\'f1.log\', \'f2.log\') #目标文件必须存在 17 18 #shutil.ignore_patterns(*patterns) 19 #shutil.copytree(src, dst, symlinks=False, ignore=None) 20 #递归的去拷贝文件夹 21 shutil.copytree(\'folder1\', \'folder2\',ignore=shutil.ignore_patterns(\'*.pyc\', \'tmp*\')) 22 # 目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 23 24 #shutil.rmtree(path[, ignore_errors[, onerror]])递归的去删除文件 25 shutil.rmtree(\'folder1\') 26 27 #shutil.move(src, dst)递归的去移动文件,它类似mv命令,其实就是重命名。 28 shutil.move(\'folder1\', \'folder3\')
shutil乱七八糟的操作
shutil.make_archive(base_name, format,…)
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如 data_bak =>保存至当前路径
如:/tmp/data_bak =>保存至/tmp/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
1 import zipfile 2 3 # 压缩 4 z = zipfile.ZipFile(\'laxi.zip\', \'w\') 5 z.write(\'a.log\') 6 z.write(\'data.data\') 7 z.close() 8 9 # 解压 10 z = zipfile.ZipFile(\'laxi.zip\', \'r\') 11 z.extractall(path=\'.\') 12 z.close()
zipfile压缩&解压
1 import tarfile 2 3 # 压缩 4 >>> t=tarfile.open(\'/tmp/egon.tar\',\'w\') 5 >>> t.add(\'/test1/a.py\',arcname=\'a.bak\') 6 >>> t.add(\'/test1/b.py\',arcname=\'b.bak\') 7 >>> t.close() 8 9 10 # 解压 11 >>> t=tarfile.open(\'/tmp/egon.tar\',\'r\') 12 >>> t.extractall(\'/egon\') 13 >>> t.close()
tarfile压缩&解压
(10)PyYaml模块
Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,
参考文档 http://pyyaml.org/wiki/PyYAMLDocumentation
(11)cofigpaser模块
用于生成和修改常见配置文档
来看一个好多软件的常见文档格式如下:
1 [DEFAULT] 2 ServerAliveInterval = 45 3 Compression = yes 4 CompressionLevel = 9 5 ForwardX11 = yes 6 7 [bitbucket.org] 8 User = hg 9 10 [topsecret.server.com] 11 Port = 50022 12 ForwardX11 = no
我是没见过
如果想用python生成一个这样的文档怎么做呢?
1 import configparser 2 3 config = configparser.ConfigParser() 4 config["DEFAULT"] = {\'ServerAliveInterval\': \'45\', 5 \'Compression\': \'yes\', 6 \'CompressionLevel\': \'9\'} 7 8 config[\'bitbucket.org\'] = {} 9 config[\'bitbucket.org\'][\'User\'] = \'hg\' 10 config[\'topsecret.server.com\'] = {} 11 topsecret = config[\'topsecret.server.com\'] 12 topsecret[\'Host Port\'] = \'50022\' # mutates the parser 13 topsecret[\'ForwardX11\'] = \'no\' # same here 14 config[\'DEFAULT\'][\'ForwardX11\'] = \'yes\' 15 with open(\'example.ini\', \'w\') as configfile: 16 config.write(configfile)
python写配置文档
写完了还能再读:
1 >>> import configparser 2 >>> config = configparser.ConfigParser() 3 >>> config.sections() 4 [] 5 >>> config.read(\'example.ini\') 6 [\'example.ini\'] 7 >>> config.sections() 8 [\'bitbucket.org\', \'topsecret.server.com\'] 9 >>> \'bitbucket.org\' in config 10 True 11 >>> \'bytebong.com\' in config 12 False 13 >>> config[\'bitbucket.org\'][\'User\'] 14 \'hg\' 15 >>> config[\'DEFAULT\'][\'Compression\'] 16 \'yes\' 17 >>> topsecret = config[\'topsecret.server.com\'] 18 >>> topsecret[\'ForwardX11\'] 19 \'no\' 20 >>> topsecret[\'Port\'] 21 \'50022\' 22 >>> for key in config[\'bitbucket.org\']: print(key) 23 ... 24 user 25 compressionlevel 26 serveraliveinterval 27 compression 28 forwardx11 29 >>> config[\'bitbucket.org\'][\'ForwardX11\'] 30 \'yes\'
python读取配置文档
1 [section1] 2 k1 = v1 3 k2:v2 4 5 [section2] 6 k1 = v1 7 8 import ConfigParser 9 10 config = ConfigParser.ConfigParser() 11 config.read(\'i.cfg\') 12 13 # ########## 读 ########## 14 #secs = config.sections() 15 #print secs 16 #options = config.options(\'group2\') 17 #print options 18 19 #item_list = config.items(\'group2\') 20 #print item_list 21 22 #val = config.get(\'group1\',\'key\') 23 #val = config.getint(\'group1\',\'key\') 24 25 # ########## 改写 ########## 26 #sec = config.remove_section(\'group1\') 27 #config.write(open(\'i.cfg\', "w")) 28 29 #sec = config.has_section(\'wupeiqi\') 30 #sec = config.add_section(\'wupeiqi\') 31 #config.write(open(\'i.cfg\', "w")) 32 33 34 #config.set(\'group2\',\'k1\',11111) 35 #config.write(open(\'i.cfg\', "w")) 36 37 #config.remove_option(\'group2\',\'age\') 38 #config.write(open(\'i.cfg\', "w"))
增删改查
(12)hashlib模块
用于加密相关的操作,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
1 import hashlib 2 3 m = hashlib.md5() 4 m.update(b"Hello") 5 m.update(b"It\'s me") 6 print(m.digest()) 7 m.update(b"It\'s been a long time since last time we ...") 8 9 print(m.digest()) #2进制格式hash 10 print(len(m.hexdigest())) #16进制格式hash 11 \'\'\' 12 def digest(self, *args, **kwargs): # real signature unknown 13 """ Return the digest value as a string of binary data. """ 14 pass 15 16 def hexdigest(self, *args, **kwargs): # real signature unknown 17 """ Return the digest value as a string of hexadecimal digits. """ 18 pass 19 20 \'\'\' 21 import hashlib 22 23 # ######## md5 ######## 24 25 hash = hashlib.md5() 26 hash.update(\'admin\') 27 print(hash.hexdigest()) 28 29 # ######## sha1 ######## 30 31 hash = hashlib.sha1() 32 hash.update(\'admin\') 33 print(hash.hexdigest()) 34 35 # ######## sha256 ######## 36 37 hash = hashlib.sha256() 38 hash.update(\'admin\') 39 print(hash.hexdigest()) 40 41 42 # ######## sha384 ######## 43 44 hash = hashlib.sha384() 45 hash.update(\'admin\') 46 print(hash.hexdigest()) 47 48 # ######## sha512 ######## 49 50 hash = hashlib.sha512() 51 hash.update(\'admin\') 52 print(hash.hexdigest())
hashlib模块,试试吧
python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密
散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪;
1 import hmac 2 h = hmac.new(b\'天王盖地虎\', b\'宝塔镇河妖\') 3 print h.hexdigest()
hmac加密
更多关于md5,sha1,sha256等介绍的文章看这里
https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
(13)re模块
常用正则表达式符号:五种匹配语法、三种匹配模式
1 \'.\' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 2 \'^\' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) 3 \'$\' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以 4 \'*\' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为[\'abb\', \'ab\', \'a\'] 5 \'+\' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果[\'ab\', \'abb\'] 6 \'?\' 匹配前一个字符1次或0次 7 \'{m}\' 匹配前一个字符m次 8 \'{n,m}\' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果\'abb\', \'ab\', \'abb\'] 9 \'|\' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果\'ABC\' 10 \'(...)\' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
常用的正则表达式1
1 \'\A\' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的 2 \'\Z\' 匹配字符结尾,同$ 3 \'\d\' 匹配数字0-9 4 \'\D\' 匹配非数字 5 \'\w\' 匹配[A-Za-z0-9] 6 \'\W\' 匹配非[A-Za-z0-9] 7 \'s\' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 \'\t\'
常用的正则表达式2
1 \'(?P<name>...)\' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{\'province\': \'3714\', \'city\': \'81\', \'birthday\': \'1993\'}
分组匹配身份证号
1 re.match 从头开始匹配 2 re.search 匹配包含 3 re.findall 把所有匹配到的字符放到以列表中的元素返回 4 re.splitall 以匹配到的字符当做列表分隔符 5 re.sub 匹配字符并替换
匹配语法
1 re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同) 2 M(MULTILINE): 多行模式,改变\'^\'和\'$\'的行为(参见上图) 3 S(DOTALL): 点任意匹配模式,改变\'.\'的行为
匹配模式
下面来看看实例操作:(命令行操作)
1 >>> re.match("^Kanghui","Kanghui123") 2 <_sre.SRE_Match object; span=(0, 7), match=\'Kanghui\'> 3 #这是匹配到的情况,如果匹配不到呢?是没有反应的。就是none 4 >>> re.match("^aKanghui","Kanghui123") 5 >>> re.match("^aKanghui","Kanghui123") 6 #查看匹配内容 7 >>> res =re.match("^Kanghui","Kanghui123") 8 >>> res.group() 9 \'Kanghui\' 10 #现在这样还没用到正则,那么接下来~我要把后面的数字也匹配进来 11 >>> res =re.match("^Kang\d","Kang123hui123") 12 >>> res.group() 13 \'Kang1\' 14 #现在只有一个数字,多个数字就再加一个+ 15 >>> res =re.match("^Kang\d+","Kang123hui123") 16 >>> res.group() 17 \'Kang123\' 18 #接下来开始正式使用正则表示式符号 19 >>> re.match("^.\d+","Kang123hui123") 20 >>> re.match("^.\d+","Kang123hui123") 21 #这样为什么没有反应呢?原因是因为 ^匹配字符开头, .默认匹配除\n之外的任意一个字符 一个字符之后就是数字所以不行 22 >>> re.match("^.+\d+","Kang123hui123") 23 <_sre.SRE_Match object; span=(0, 13), match=\'Kang123hui123\'> 24 >>> re.match("^.+","Kang123hui123") 25 <_sre.SRE_Match object; span=(0, 13), match=\'Kang123hui123\'> 26 >>> re.match(".+","Kang123hui123") 27 <_sre.SRE_Match object; span=(0, 13), match=\'Kang123hui123\'> 28 >>> re.match(".","Kang123hui123") 29 <_sre.SRE_Match object; span=(0, 1), match=\'K\'> 30 >>> re.match("^K.+","Kang123hui123") 31 <_sre.SRE_Match object; span=(0, 13), match=\'Kang123hui123\'> 32 #如果我只想要数字中间的部分呢? 33 >>> re.search("^h.+i","Kang123hui321") #^匹配字符开头 34 >>> re.search("h.+i","Kang123hui321") 35 <_sre.SRE_Match object; span=(7, 10), match=\'hui\'>
re模块引入
1 >>> re.search("^h.+i","Kang123hui321") 2 >>> re.search("h.+i","Kang123hui321") 3 <_sre.SRE_Match object; span=(7, 10), match=\'hui\'> 4 >>> re.search("$","Kang123hui321a") 5 <_sre.SRE_Match object; span=(14, 14), match=\'\'> 6 >>> re.search("a$","Kang123hui321a") 7 <_sre.SRE_Match object; span=(13, 14), match=\'a\'> 8 >>> re.search(".+a$","Kang123hui321a") 9 <_sre.SRE_Match object; span=(0, 14), match=\'Kang123hui321a\'> 10 >>> re.search(".+a","Kang123hui321a") 11 <_sre.SRE_Match object; span=(0, 14), match=\'Kang123hui321a\'> 12 这样看起来$貌似没有什么用,因为.+是匹配任意字符。 13 >>> re.search("h[a-z]+","Kang123hui321a") 14 <_sre.SRE_Match object; span=(7, 10), match=\'hui\'> 15 >>> re.search("h[a-z]+i","Kang123hui321i") 16 <_sre.SRE_Match object; span=(7, 10), match=\'hui\'> 17 >>> re.search("h[a-z]+i$","Kang123hui321i") 18 >>> re.search("h[a-zA-Z]+i","Kang123huiKAnghui321i") 19 <_sre.SRE_Match object; span=(7, 17), match=\'huiKAnghui\'> 20 >>> re.search("#.+#","123#hello#") 21 <_sre.SRE_Match object; span=(3, 10), match=\'#hello#\'> 22 >>> re.search("aaa?","alexaaa") 23 <_sre.SRE_Match object; span=(4, 7), match=\'aaa\'> 24 >>> re.search("aaa?","aalexaaa") 25 <_sre.SRE_Match object; span=(0, 2), match=\'aa\'> 26 >>> re.search("aal?","aalexaaa") 27 <_sre.SRE_Match object; span=(0, 3), match=\'aal\'> 28 >>> re.search("aal?","aaexaaa") 29 <_sre.SRE_Match object; span=(0, 2), match=\'aa\'> 30 >>> re.search("[0-9]{3}","a8l26e456x") 31 <_sre.SRE_Match object; span=(6, 9), match=\'456\'> 32 >>> re.search("[0-9]{1,3}","a8l26e456x") 33 <_sre.SRE_Match object; span=(1, 2), match=\'8\'> 34 #如果想要匹配所有的数字呢?用findall试试:
re.search
1 >>> re.search("[0-9]{1,3}","a8l26e456x") 2 <_sre.SRE_Match object; span=(1, 2), match=\'8\'> 3 >>> re.findall("[0-9]{1,2}","a8l26e456x") 4 [\'8\', \'26\', \'45\', \'6\'] 5 >>> re.findall("[0-9]{1,3}","a8l26e456x") 6 [\'8\', \'26\', \'456\'] 7 >>> re.search("abc|ABC","ABCabcCDE") 8 <_sre.SRE_Match object; span=(0, 3), match=\'ABC\'> 9 >>> re.search("abc|ABC","ABCabcCDE").group() 10 \'ABC\' 11 >>> re.findall("abc|ABC","ABCabcCDE").group() 12 Traceback (most recent call last): 13 File "<stdin>", line 1, in <module> 14 AttributeError: \'list\' object has no attribute \'group\' 15 >>> re.findall("abc|ABC","ABCabcCDE") 16 [\'ABC\', \'abc\'] 17 >>> re.search("(abc){2}","subjectabccccabc") 18 >>> re.search("(abc){2}","subjectabccccabcabc") 19 <_sre.SRE_Match object; span=(13, 19), match=\'abcabc\'> 20 >>> re.search("(abc){2}\|","subjectabccccabcabc|") 21 <_sre.SRE_Match object; span=(13, 20), match=\'abcabc|\'> 22 >>> re.search("(abc){2}\|\|=","subjectabccccabcabc||=||=") 23 <_sre.SRE_Match object; span=(13, 22), match=\'abcabc||=\'> 24 >>> re.search("\D+","123#abc") 25 <_sre.SRE_Match object; span=(3, 7), match=\'#abc\'> 26 >>> re.search("\s+","123#abc \r\n ") 27 <_sre.SRE_Match object; span=(7, 11), match=\' \r\n\t\'>
re.findall
1 >>> re.split("[0-9]","abc12de3f45g6HGD") 2 [\'abc\', \'\', \'de\', \'f\', \'\', \'g\', \'HGD\'] 3 >>> re.split("[0-9]+","abc12de3f45g6HGD") 4 [\'abc\', \'de\', \'f\', \'g\', \'HGD\']
re.split
1 >>> re.sub("[0-9]+","|","abc12de3f45g6HGD") 2 \'abc|de|f|g|HGD\' 3 >>> re.sub("[0-9]+","|","abc12de3f45g6HGD",count=2) 4 \'abc|de|f45g6HGD\'
re.sub
最后来个使用性的例子:身份证号码的每个数字都代表着什么你知道吗?
科普:
身份证号码编排规则(18位身份证号码)
公民身份证号码是特征组合码,由17位数字本体码和1位校验码组成。前1、2位数字表示:所在省份的代码;第3、4位数字表示:所在城市的代码;第5、 6位数字表示:所在区县的代码;第7~14位数字表示:出生年、月、日;第15、16位数字表示:所在地的派出所的代码;第17位数字表示性别:奇数表示男性,偶数表示女性;第18位数字是校检码:用来检验身份证号码的正确性,校检码由0~9的数字、及X表示。
1 >>> re.search("(?P<province>[0-9]{2})(?P<city>[0-9]{2})(?P<county>[0-9]{2})(?P<birthday>[0-9]{4})","412727199511282319").groupdict("city") 2 {\'province\': \'41\', \'city\': \'27\', \'county\': \'27\', \'birthday\': \'1995\'}
通过正则取出身份信息
5 练习(开发一个简单的python计算器)
需求:
1实现加减乘除和括号优先级的解析
2用户输入1-2*((60-30)+(40/5)*)等类的公式后,必须自己解析里面的运算符号,运算后得出结果,结果必须与真实计算器一致。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 """ 4 该计算器思路: 5 1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果 6 2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数 7 使用技术: 8 1、正则表达式 9 2、递归 10 11 执行流程如下: 12 ******************** 请计算表达式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ******************** 13 before: [\'1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 14 -40.0/5=-8.0 15 after: [\'1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 16 ========== 上一次计算结束 ========== 17 before: [\'1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 18 9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953 19 after: [\'1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))\'] 20 ========== 上一次计算结束 ========== 21 before: [\'1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))\'] 22 60-30+-8.0*173545.880953=-1388337.04762 23 after: [\'1-2*(-1388337.04762-(-4*3)/(16-3*2))\'] 24 ========== 上一次计算结束 ========== 25 before: [\'1-2*(-1388337.04762-(-4*3)/(16-3*2))\'] 26 -4*3=-12.0 27 after: [\'1-2*(-1388337.04762--12.0/(16-3*2))\'] 28 ========== 上一次计算结束 ========== 29 before: [\'1-2*(-1388337.04762--12.0/(16-3*2))\'] 30 16-3*2=10.0 31 after: [\'1-2*(-1388337.04762--12.0/10.0)\'] 32 ========== 上一次计算结束 ========== 33 before: [\'1-2*(-1388337.04762--12.0/10.0)\'] 34 -1388337.04762--12.0/10.0=-1388335.84762 35 after: [\'1-2*-1388335.84762\'] 36 ========== 上一次计算结束 ========== 37 我的计算结果: 2776672.69524 38 """ 39 40 41 import re 42 43 44 def compute_mul_div(arg): 45 """ 操作乘除 46 :param expression:表达式 47 :return:计算结果 48 """ 49 50 val = arg[0] 51 mch = re.search(\'\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*\', val) 52 if not mch: 53 return 54 content = re.search(\'\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*\', val).group() 55 56 if len(content.split(\'*\'))>1: 57 n1, n2 = content.split(\'*\') 58 value = float(n1) * float(n2) 59 else: 60 n1, n2 = content.split(\'/\') 61 value = float(n1) / float(n2) 62 63 before, after = re.split(\'\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*\', val, 1) 64 new_str = "%s%s%s" % (before,value,after) 65 arg[0] = new_str 66 compute_mul_div(arg) 67 68 69 def compute_add_sub(arg): 70 """ 操作加减 71 :param expression:表达式 72 :return:计算结果 73 """ 74 while True: 75 if arg[0].__contains__(\'+-\') or arg[0].__contains__("++") or arg[0].__contains__(\'-+\') or arg[0].__contains__("--"): 76 arg[0] = arg[0].replace(\'+-\',\'-\') 77 arg[0] = arg[0].replace(\'++\',\'+\') 78 arg[0] = arg[0].replace(\'-+\',\'-\') 79 arg[0] = arg[0].replace(\'--\',\'+\') 80 else: 81 break 82 83 if arg[0].startswith(\'-\'): 84 arg[1] += 1 85 arg[0] = arg[0].replace(\'-\',\'&\') 86 arg[0] = arg[0].replace(\'+\',\'-\') 87 arg[0] = arg[0].replace(\'&\',\'+\') 88 arg[0] = arg[0][1:] 89 val = arg[0] 90 mch = re.search(\'\d+\.*\d*[\+\-]{1}\d+\.*\d*\', val) 91 if not mch: 92 return 93 content = re.search(\'\d+\.*\d*[\+\-]{1}\d+\.*\d*\', val).group() 94 if len(content.split(\'+\'))>1: 95 n1, n2 = content.split(\'+\') 96 value = float(n1) + float(n2) 97 else: 98 n1, n2 = content.split(\'-\') 99 value = float(n1) - float(n2) 100 101 before, after = re.split(\'\d+\.*\d*[\+\-]{1}\d+\.*\d*\', val, 1) 102 new_str = "%s%s%s" % (before,value,after) 103 arg[0] = new_str 104 compute_add_sub(arg) 105 106 107 def compute(expression): 108 """ 操作加减乘除 109 :param expression:表达式 110 :return:计算结果 111 """ 112 inp = [expression,0] 113 114 # 处理表达式中的乘除 115 compute_mul_div(inp) 116 117 # 处理 118 compute_add_sub(inp) 119 if divmod(inp[1],2)[1] == 1: 120 result = float(inp[0]) 121 result = result * -1 122 else: 123 result = float(inp[0]) 124 return result 125 126 127 def exec_bracket(expression): 128 """ 递归处理括号,并计算 129 :param expression: 表达式 130 :return:最终计算结果 131 """ 132 # 如果表达式中已经没有括号,则直接调用负责计算的函数,将表达式结果返回,如:2*1-82+444 133 if not re.search(\'\(([\+\-\*\/]*\d+\.*\d*){2,}\)\', expression): 134 final = compute(expression) 135 return final 136 # 获取 第一个 只含有 数字/小数 和 操作符 的括号 137 # 如: 138 # [\'1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 139 # 找出:(-40.0/5) 140 content = re.search(\'\(([\+\-\*\/]*\d+\.*\d*){2,}\)\', expression).group() 141 142 # 分割表达式,即: 143 # 将[\'1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 144 # 分割更三部分:[\'1-2*((60-30+( (-40.0/5) *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 145 before, nothing, after = re.split(\'\(([\+\-\*\/]*\d+\.*\d*){2,}\)\', expression, 1) 146 147 print \'before:\',expression 148 content = content[1:len(content)-1] 149 150 # 计算,提取的表示 (-40.0/5),并活的结果,即:-40.0/5=-8.0 151 ret = compute(content) 152 153 print \'%s=%s\' %( content, ret) 154 155 # 将执行结果拼接,[\'1-2*((60-30+( -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 156 expression = "%s%s%s" %(before, ret, after) 157 print \'after:\',expression 158 print "="*10,\'上一次计算结束\',"="*10 159 160 # 循环继续下次括号处理操作,本次携带者的是已被处理后的表达式,即: 161 # [\'1-2*((60-30+ -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\'] 162 163 # 如此周而复始的操作,直到表达式中不再含有括号 164 return exec_bracket(expression) 165 166 167 168 # 使用 __name__ 的目的: 169 # 只有执行 python index.py 时,以下代码才执行 170 # 如果其他人导入该模块,以下代码不执行 171 if __name__ == "__main__": 172 #print \'*\'*20,"请计算表达式:", "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" ,\'*\'*20 173 #inpp = \'1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) \' 174 inpp = "1-2*-30/-12*(-20+200*-3/-200*-300-100)" 175 #inpp = "1-5*980.0" 176 inpp = re.sub(\'\s*\',\'\',inpp) 177 # 表达式保存在列表中 178 result = exec_bracket(inpp) 179 print result
代码示例
6 小结
做一名程序猿是真的不容易。
最近才觉得好多东西要学啊,亚历山大~~!!!自己就像一张白纸,慢慢填~
坚持~
为什么明明才二十几岁,就感觉一辈子好像就这样了呢?
别忘了看书。
我是尾巴~
这次推荐一个远程控制电脑的黑科技:
https://mp.weixin.qq.com/s/SE5QGzwJhA1lKbVuhS9_bg
虽不才,才要坚持~