第十章 开箱即用

第十章 开箱即用

“开箱即用”(batteries included)最初是由Frank Stajano提出的,指的是Python丰富的标准库

模块

使用import将函数从外部模块导入到程序中。

import math
math.sin(0)#结果为:0.0

模块就是程序

在文件夹中创建一个test.py,内容如下:

#text.py
print("hello beyond band!")

在这里插入图片描述
位置如下:
在这里插入图片描述
sys.path包含一个目录(表示为字符串)列表,解释器将在这些目录中查找模块。

import sys
sys.path.append('E:\Jupyter_workspace\study\python\book')import text#结果为:hello beyond band!

程序运行完之后会生成一个__pycache__文件夹,这个目录包含处理后的文件,Python能够更高效地处理它们。
以后再导入这个模块时,如果.py文件未发生变化,Python将导入处理后的文件,否则将重新生成处理后的文件。
在这里插入图片描述
导入这个模块时,执行了其中的代码。但如果再次导入它,什么事情都不会发生
模块并不是用来执行操作(如打印文本)的,而是用于定义变量、函数、类等。

模块是用来下定义的

模块在首次被导入程序时执行。
在模块中定义的类和函数以及对其进行赋值的变量都将成为模块的属性。

1,在模块中定义函数
创建hellp.py
内容如下:

#hello.py
def hello():print("Hello beyond!!!")

在另一个py文件中导入该模块

import sys
sys.path.append('E:\Jupyter_workspace\study\python\book')import hellohello.hello()#结果为:Hello beyond!!!

在模块的全局作用域内定义的名称都可像上面这样访问。

为何不在主程序中定义一切呢?
主要是为了重用代码通过将代码放在模块中,就可在多个程序中使用它们。

2,在模块中添加测试代码
检查模块是作为程序运行还是被导入另一个程序。为此,需要使用变量__name__

在上面的基础上进行测试:

import sys
sys.path.append('E:\Jupyter_workspace\study\python\book')import hellohello.hello()#结果为:Hello beyond!!!__name__#结果为:'__main__'
hello.__name__#结果为:'hello'

在主程序中(包括解释器的交互式提示符),变量__name__的值是’__main__’,
而在导入的模块中,这个变量被设置为该模块的名称

一个包含有条件地执行的测试代码的模块
创建beyond.py
内容如下:

#beyond.py
def hello():print("beyond!")def test():hello()if __name__ == '__main__':test()

如果将这个模块作为程序运行,将执行函数hello;
如果导入它,其行为将像普通模块一样。

在另一个py文件中导入该模块

import sys
sys.path.append('E:\Jupyter_workspace\study\python\book')import beyondbeyond.hello()#结果为:beyond!
beyond.test()#结果为:beyond!

将测试代码放在了函数test中。原本可以将这些代码直接放在if语句中,但通过将其放在一个独立的测试函数中,可在程序中导入模块并对其进行测试。

让模块可用

1,将模块放在正确的位置

将模块放在正确的位置很容易,只需找出Python解释器到哪里去查找模块,再将文件放在这个地方即可。

模块sys的变量path中找到目录列表(即搜索路径)。
如果要打印的数据结构太大,一行容纳不下,可使用模块pprint中的函数pprint(而不是普通print语句)。pprint是个卓越的打印函数,能够更妥善地打印输出

import sys,pprint
pprint.pprint(sys.path)#结果为:
'''
['','D:\\Anaconda3\\python36.zip','D:\\Anaconda3\\DLLs','D:\\Anaconda3\\lib','D:\\Anaconda3','D:\\Anaconda3\\lib\\site-packages','D:\\Anaconda3\\lib\\site-packages\\Babel-2.5.0-py3.6.egg','D:\\Anaconda3\\lib\\site-packages\\win32','D:\\Anaconda3\\lib\\site-packages\\win32\\lib','D:\\Anaconda3\\lib\\site-packages\\Pythonwin','D:\\Anaconda3\\lib\\site-packages\\IPython\\extensions','C:\\Users\\yanyu\\.ipython','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook','E:\\Jupyter_workspace\\study\\python\x08ook']
'''

每个字符串都表示一个位置,如果要让解释器能够找到模块,可将其放在其中任何一个位置中。目录site-packages是最佳的选择,因为它就是用来放置模块的

只要模块位于类似于site-packages这样的地方,所有的程序就都能够导入它。
将上述的beyond.py文件放入到site-packages文件夹下。
在这里插入图片描述
故在其他程序中可以直接导入即可:

import beyond
beyond.hello()#结果为:beyond!

2,告诉解析器到哪里去查找

将模块放在正确的位置可能不是合适的解决方案,其中的原因很多
1,不希望Python解释器的目录中充斥着你编写的模块。
2,没有必要的权限,无法将文件保存到Python解释器的目录中。
3,想将模块放在其他地方。
4,如果将模块放在其他地方,就必须告诉解释器到哪里去查找。
标准做法解释
1,将模块所在的目录包含在环境变量PYTHONPATH中环境变量PYTHONPATH的内容随操作系统而异,但它基本上类似于sys.path,也是一个目录列表。
2,使用路径配置文件这些文件的扩展名为.pth,位于一些特殊目录中,包含要添加到sys.path中的目录。

为组织模块,可将其编组为包(package)。
包其实就是另一种模块(可包含其他模块的模块)。

模块存储在扩展名为.py的文件中,而则是一个目录

要被Python视为包,目录必须包含文件__init__.py

要将模块加入包中,只需将模块文件放在包目录中即可。还可以在包中嵌套其他包

按照下面的五个文件夹路径创建对应的文件和文件夹

文件/目录描述
~/python/PYTHONPATH中的目录
~/python/drawing/包目录(包drawing)
~/python/drawing/__init__.py包代码(模块drawing)
~/python/drawing/colors.py模块colors
~/python/drawing/shapes.py模块shapes
import drawing#导入drawing包
import drawing.colors#导入drawing包中的模块colors
from drawing import shapes#导入模块shapes
'''
执行第1条语句后,便可使用目录drawing中文件__init__.py的内容,但不能使用模块shapes和colors的内容。
执行第2条语句后,便可使用模块colors,但只能通过全限定名drawing.colors来使用。
执行第3条语句后,便可使用简化名(即shapes)来使用模块shapes。
'''

探索模块

模块包含什么

接下来以一个名为copy的标准模块来进行解释:

import copy

没有引发异常,说明确实有这样的模块。

1,使用dir
函数dir,它列出对象的所有属性(对于模块,它列出所有的函数、类、变量等)
在这些名称中,有几个以下划线打头。根据约定,这意味着它们并非供外部使用。
使用一个简单的列表推导将这些名称过滤掉。
[n for n in dir(copy) if not n.startswith('_')] 结果包含dir(copy)返回的不以下划线打头的名称,

import copy
dir(copy)#结果为:
"""
['Error','__all__','__builtins__','__cached__','__doc__','__file__','__loader__','__name__','__package__','__spec__','_copy_dispatch','_copy_immutable','_deepcopy_atomic','_deepcopy_dict','_deepcopy_dispatch','_deepcopy_list','_deepcopy_method','_deepcopy_tuple','_keep_alive','_reconstruct','copy','deepcopy','dispatch_table','error']
"""[n for n in dir(copy) if not n.startswith('_')]#结果为:['Error', 'copy', 'deepcopy', 'dispatch_table', 'error']

2,变量__all__
由上述的代码段可知,在dir(copy)返回的完整清单中,包含名称__all__。
__all__这个变量包含一个列表,它与前面使用列表推导创建的列表类似,但是在模块内部设置的。

import copy
copy.__all__#结果为:['Error', 'copy', 'deepcopy']

使用help获取帮助

使用help获取有关函数copy的信息

help(copy.copy)#结果为:
'''
Help on function copy in module copy:copy(x)Shallow copy operation on arbitrary Python objects.See the module's __doc__ string for more info.
'''

上述帮助信息指出,函数copy只接受一个参数x,且执行的是浅复制
帮助信息是从函数copy的文档字符串中提取的

print(copy.copy.__doc__)#结果为:
'''
Shallow copy operation on arbitrary Python objects.See the module's __doc__ string for more info.
'''

相比于直接查看文档字符串,使用help的优点是可获取更多的信息,如函数的特征标(即它接受的参数)

对模块copy本身调用help

help(copy)#结果为:
'''
Help on module copy:NAMEcopy - Generic (shallow and deep) copying operations.DESCRIPTIONInterface summary:import copyx = copy.copy(y)        # make a shallow copy of yx = copy.deepcopy(y)    # make a deep copy of yFor module specific errors, copy.Error is raised.The difference between shallow and deep copying is only relevant forcompound objects (objects that contain other objects, like lists orclass instances).- A shallow copy constructs a new compound object and then (to theextent possible) inserts *the same objects* into it that theoriginal contains.- A deep copy constructs a new compound object and then, recursively,inserts *copies* into it of the objects found in the original.Two problems often exist with deep copy operations that don't existwith shallow copy operations:a) recursive objects (compound objects that, directly or indirectly,contain a reference to themselves) may cause a recursive loopb) because deep copy copies *everything* it may copy too much, e.g.administrative data structures that should be shared even betweencopiesPython's deep copy operation avoids these problems by:a) keeping a table of objects already copied during the currentcopying passb) letting user-defined classes override the copying operation or theset of components copiedThis version does not copy types like module, class, function, method,nor stack trace, stack frame, nor file, socket, window, nor array, norany similar types.Classes can use the same interfaces to control copying that they useto control pickling: they can define methods called __getinitargs__(),__getstate__() and __setstate__().  See the documentation for module"pickle" for information on these methods.CLASSESbuiltins.Exception(builtins.BaseException)Errorclass Error(builtins.Exception)|  Common base class for all non-exit exceptions.|  |  Method resolution order:|      Error|      builtins.Exception|      builtins.BaseException|      builtins.object|  |  Data descriptors defined here:|  |  __weakref__|      list of weak references to the object (if defined)|  |  ----------------------------------------------------------------------|  Methods inherited from builtins.Exception:|  |  __init__(self, /, *args, **kwargs)|      Initialize self.  See help(type(self)) for accurate signature.|  |  __new__(*args, **kwargs) from builtins.type|      Create and return a new object.  See help(type) for accurate signature.|  |  ----------------------------------------------------------------------|  Methods inherited from builtins.BaseException:|  |  __delattr__(self, name, /)|      Implement delattr(self, name).|  |  __getattribute__(self, name, /)|      Return getattr(self, name).|  |  __reduce__(...)|      helper for pickle|  |  __repr__(self, /)|      Return repr(self).|  |  __setattr__(self, name, value, /)|      Implement setattr(self, name, value).|  |  __setstate__(...)|  |  __str__(self, /)|      Return str(self).|  |  with_traceback(...)|      Exception.with_traceback(tb) --|      set self.__traceback__ to tb and return self.|  |  ----------------------------------------------------------------------|  Data descriptors inherited from builtins.BaseException:|  |  __cause__|      exception cause|  |  __context__|      exception context|  |  __dict__|  |  __suppress_context__|  |  __traceback__|  |  argsFUNCTIONScopy(x)Shallow copy operation on arbitrary Python objects.See the module's __doc__ string for more info.deepcopy(x, memo=None, _nil=[])Deep copy operation on arbitrary Python objects.See the module's __doc__ string for more info.DATA__all__ = ['Error', 'copy', 'deepcopy']FILEd:\anaconda3\lib\copy.py
'''

文档

文档是有关模块信息的自然来源

例如,你可能想知道range的参数是什么?
在这种情况下,与其在Python图书或标准Python文档中查找对range的描述,不如直接检查这个函数。

print(range.__doc__)#结果为:
'''
range(stop) -> range object
range(start, stop[, step]) -> range objectReturn an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
'''

Python库参考手册”(https://docs.python.org/library

使用源代码

要学习Python,阅读源代码是除动手编写代码外的最佳方式。
假设你要阅读标准模块copy的代码,可以在什么地方找到呢?

print(copy.__file__)#结果为:D:\Anaconda3\lib\copy.py

你可在代码编辑器(如IDLE)中打开文件copy.py,并开始研究其工作原理。

标准库:一些深受欢迎的模块

sys

模块sys让你能够访问与Python解释器紧密相关的变量和函数。

函数/变量描述
argv命令行参数,包括脚本名
exit([arg])退出当前程序,可通过可选参数指定返回值或错误消息
modules一个字典,将模块名映射到加载的模块
path一个列表,包含要在其中查找模块的目录的名称
platform一个平台标识符,如sunos5或win32
stdin标准输入流——一个类似于文件的对象
stdout标准输出流——一个类似于文件的对象
stderr标准错误流——一个类似于文件的对象

反转并打印命令行参数
创建了一个sys.argv的副本,也可修改sys.argv。

import sys
args = sys.argv[1:]
args.reverse()
print(' '.join(args))#结果为:C:\Users\yanyu\AppData\Roaming\jupyter\runtime\kernel-17c0e23a-ea6e-40f9-98dc-68588128f0cc.json -fprint(' '.join(reversed(sys.argv[1:])))#结果为:C:\Users\yanyu\AppData\Roaming\jupyter\runtime\kernel-17c0e23a-ea6e-40f9-98dc-68588128f0cc.json -f

os

模块os让你能够访问多个操作系统服务。

os及其子模块os.path还包含多个查看、创建和删除目录及文件的函数,以及一些操作路径的函数(例如,os.path.split和os.path.join让你在大多数情况下都可忽略os.pathsep)。

函数/变量描述
environ包含环境变量的映射
system(command)在子shell中执行操作系统命令
sep路径中使用的分隔符
pathsep分隔不同路径的分隔符
linesep行分隔符(’\n’、’\r’或’\r\n’)
urandom(n)返回n个字节的强加密随机数据

要访问环境变量PYTHONPATH,可使用表达式os.environ['PYTHONPATH']

变量os.sep是用于路径名中的分隔符。
在Windows中,标准分隔符为\\(这种Python语法表示单个反斜杠)
在UNIX(以及macOS的命令行Python版本)中,标准分隔符为/

变量os.linesep是用于文本文件中的行分隔符:
在UNIX/OS X中为单个换行符(\n
在Windows中为回车和换行符(\r\n

启动图形用户界面程序,如Web浏览器
在UNIX中:假设目录为/usr/bin/firefox

import os
os.system('/usr/bin/firefox')

在Windows中:假设目录为C:\Program Files\Mozilla Firefox
这里用引号将Program Files和Mozilla Firefox括起来了。
如果不这样做,底层shell将受阻于空白处(对于PYTHONPATH中的路径,也必须这样做)。
另外,这里必须使用反斜杆,因为 Windows shell 无法识别斜杠。

import os
os.system(r'C:\"Program Files"\"Mozilla Firefox"\firefox.exe')

Windows特有的函数os.startfile,也可以完成该操作

import os
os.startfile(r'C:\Program Files\Mozilla Firefox\firefox.exe')

就启动Web浏览器这项任务而言,使用模块webbrowser,这个模块包含一个名为open的函数,让你能够启动默认Web浏览器并打开指定的URL。

import webbrowser
webbrowser.open('https://beyondyanyu.blog.csdn.net/')

fileinput

模块fileinput让你能够轻松地迭代一系列文本文件中的所有行。

函数描述
input([files[, inplace[, backup]]])帮助迭代多个输入流中的行
filename()返回当前文件的名称
lineno()返回(累计的)当前行号
filelineno()返回在当前文件中的行号
isfirstline()检查当前行是否是文件中的第一行
isstdin()检查最后一行是否来自sys.stdin
nextfile()关闭当前文件并移到下一个文件
close()关闭序列

fileinput.input是其中最重要的函数,它返回一个可在for循环中进行迭代的对象。

在Python脚本中添加行号
rstrip是一个字符串方法,它将删除指定字符串两端的空白,并返回结果

import fileinputfor line in fileinput.input(inplace=True):line = line.rstrip()num = fileinput.lineno()print('{:<50} # {:2d}'.format(line,num))

集合、堆和双端队列

1,集合
集合是由内置类set实现的,这意味着你可直接创建集合,而无需导入模块sets。

set(range(1,30,2))#结果为:{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29}

仅使用花括号这将创建一个空字典

type({})#结果为:dict

集合主要用于成员资格检查,因此将忽略重复的元素

{0, 1, 2, 3, 0, 1, 2, 3, 4, 5}#结果为:{0, 1, 2, 3, 4, 5}

集合中元素的排列顺序是不确定的

{'hjj', 'sq', 'hjq', 'hjj', 'hjq'}#结果为:{'hjj', 'hjq', 'sq'}

计算两个集合的并集,可对其中一个集合调用方法union也可使用按位或运算符|

a = {1,2,3}
b = {2,3,4}
a.union(b)#结果为:{1, 2, 3, 4}
a | b#结果为:{1, 2, 3, 4}

还有其他一些方法和对应的运算符

a = {1,2,3}
b = {2,3,4}
c = a & b
c.issubset(a)#结果为:Truec <= a#结果为:True
c.issuperset(a)#结果为:Falsec >= a#结果为:False
a.intersection(b)#结果为:{2, 3}a & b#结果为:{2, 3}
a.difference(b)#结果为:{1}a - b#结果为:{1}
a.symmetric_difference(b)#结果为:{1, 4}a ^ b#结果为:{1, 4}a.copy()#结果为:{1, 2, 3}
a.copy() is a#结果为:False

集合是可变的,因此不能用作字典中的键。
集合只能包含不可变(可散列)的值,因此不能包含其他集合。
frozenset类型,它表示不可变(可散列)的集合。

构造函数frozenset创建给定集合的副本。
在需要将集合作为另一个集合的成员或字典中的键时,frozenset很有用。

a = set()
b = set()
a.add(b)#报错!!!
'''
TypeError  Traceback (most recent call last)
<ipython-input-48-07ed0deb5758> in <module>()1 a = set()2 b = set()
----> 3 a.add(b)TypeError: unhashable type: 'set'
'''a.add(frozenset(b))
print(a.add(frozenset(b)))#结果为:None
print(a)#结果为:{frozenset()}
print(b)#结果为:set()

2,堆
堆(heap),它是一种优先队列。
优先队列让能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。

Python没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这个模块名为heapq(其中的q表示队列),它包含6个函数。

函数描述
heappush(heap, x)将x压入堆中
heappop(heap)从堆中弹出最小的元素
heapify(heap)让列表具备堆特征
heapreplace(heap, x)弹出最小的元素,并将x压入堆中
nlargest(n, iter)返回iter中n个最大的元素
nsmallest(n, iter)返回iter中n个最小的元素

函数heappush用于在中添加一个元素。

from heapq import *
from random import shuffle
data = list(range(10))
shuffle(data)
heap = []
for n in data:heappush(heap,n)heap#结果为:[0, 1, 5, 2, 4, 7, 9, 8, 3, 6]#位置i处的元素总是大于位置i // 2处的元素(反过来说就是小于位置2 * i和2 * i + 1处的元素)。这是底层堆算法的基础,称为堆特征(heap property)。
heappush(heap,0.5)
heap#结果为:[0, 0.5, 5, 2, 1, 7, 9, 8, 3, 6, 4]heappop(heap)#结果为:0
heappop(heap)#结果为:0.5
heappop(heap)#结果为:1heap#结果为:[2, 3, 5, 6, 4, 7, 9, 8]#函数heapify通过执行尽可能少的移位操作将列表变成合法的堆(即具备堆特征)。
heap = [5,8,0,3,6,7,9,1,4,2]
heapify(heap)
heap#结果为:[0, 1, 5, 3, 2, 7, 9, 8, 4, 6]#函数heapreplace从堆中弹出最小的元素,再压入一个新元素。
heapreplace(heap,0.5)#结果为:0
heap#结果为:[0.5, 1, 5, 3, 2, 7, 9, 8, 4, 6]
heapreplace(heap,10)#结果为:0.5
heap#结果为:[1, 2, 5, 3, 6, 7, 9, 8, 4, 10]

3,双端队列
在需要按添加元素的顺序进行删除时,双端队列很有用。
在模块collections中,包含类型deque以及其他几个集合(collection)类型。

from collections import deque
q = deque(range(5))
q.append(5)
q.appendleft(6)
q#结果为:deque([6, 0, 1, 2, 3, 4, 5])q.pop()#结果为:5
q.popleft()#结果为:6q.rotate(3)
q#结果为:deque([2, 3, 4, 0, 1])q.rotate(-1)
q#结果为:deque([3, 4, 0, 1, 2])

双端队列支持在队首(左端)高效地附加和弹出元素,还可高效地旋转元素(将元素向右或向左移,并在到达一端时环绕到另一端)。

双端队列对象还包含方法extendextendleft,其中extend类似于相应的列表方法,而extendleft类似于appendleft。
用于extendleft的可迭代对象中的元素将按相反的顺序出现在双端队列中。

time

模块time包含用于获取当前时间、操作时间和日期、从字符串中读取日期、将日期格式化为字符串的函数。

元组(2008, 1, 21, 12, 2, 56, 0, 21, 0)表示2008年1月21日12时2分56秒。这一天是星期一,2008年的第21天。

索引字段
0如2000、2001等
1范围1~1
2范围1~31
3范围0~23
4范围0~59
5范围0~61,这考虑到了闰一秒和闰两秒的情况。
6星期范围0~6,其中0表示星期一
7儒略日范围1~366
8夏令时0、1或-1,夏令时数字是一个布尔值(True或False),但如果你使用-1,那么mktime[将时间元组转换为时间戳(从新纪元开始后的秒数)的函数]可能得到正确的值。
函数描述
asctime([tuple])将时间元组转换为字符串
localtime([secs])将秒数转换为表示当地时间的日期元组
mktime(tuple)将时间元组转换为当地时间
sleep(secs)休眠(什么都不做)secs秒
strptime(string[, format])将字符串转换为时间元组
time()当前时间(从新纪元开始后的秒数,以UTC为准)

函数time.asctime将当前时间转换为字符串

import time
time.asctime()#结果为:'Sun Jan 16 10:41:41 2022'

两个较新的与时间相关的模块:datetime和timeit。
前者提供了日期和时间算术支持,而后者可帮助你计算代码段的执行时间。

random

模块random包含生成伪随机数的函数,有助于编写模拟程序或生成随机输出的程序。
虽然这些函数生成的数字好像是完全随机的,但它们背后的系统是可预测的。
真正的随机(如用于加密或实现与安全相关的功能),应考虑使用模块os中的函数urandom

函数描述
random()返回一个0~1(含)的随机实数
getrandbits(n)以长整数方式返回n个随机的二进制位
uniform(a, b)返回一个a~b(含)的随机实数
randrange([start], stop, [step])从range(start, stop, step)中随机地选择一个数
choice(seq)从序列seq中随机地选择一个元素
shuffle(seq[, random])就地打乱序列seq
sample(seq, n)从序列seq中随机地选择n个值不同的元素

函数random.random是最基本的随机函数之一,它返回一个0~1(含)的伪随机数。

首先,获取表示时间段(1998年)上限和下限的实数。为此,可使用时间元组来表示日期(将星期、儒略日和夏令时都设置为1,让Python去计算它们的正确值),并对这些元组调用mktime
接下来,以均匀的方式生成一个位于该范围内(不包括上限)的随机数
然后,将这个数转换为易于理解的日期。

from random import *
from time import *
date1 = (1998,12,2,0,0,0,-1,-1,-1)
time1 = mktime(date1)
date2 = (1999,7,5,0,0,0,-1,-1,-1)
time2 = mktime(date2)random_time = uniform(time1, time2)
print(asctime(localtime(random_time)))#结果为:Fri Feb  5 20:55:09 1999

询问用户要掷多少个骰子、每个骰子有多少面。掷骰子的机制是使用randrange和for循环实现。

from random import randrange
num = int(input('How many dice?'))
sides = int(input('How many sides per die?'))
sum = 0
for i in range(num):sum += randrange(sides) + 1
print("The result is",sum)#结果为:
'''
How many dice?3
How many sides per die?6
The result is 17
'''

shelve和json

1,一个潜在的陷阱

import shelve
s = shelve.open('database.dat')s['x'] = ['a','b','c']
s['x'].append('d')
s['x']#结果为:['a', 'b', 'c']

‘d’消失了
列表[‘a’, ‘b’, ‘c’]被存储到s的’x’键下。
获取存储的表示,并使用它创建一个新列表,再将’d’附加到这个新列表末尾,但这个修改后的版本未被存储!
最后,再次获取原来的版本——其中没有’d’。

解决方法:

import shelve
s = shelve.open('database.dat')temp = s['x']
temp.append('d')
s['x'] = temp
s['x']

2,一个简单的数据库示例

import sys,shelvedef store_person(db):pid  = input("Enter unique ID number:")person = {}person['name'] = input("Enter name:")person['age'] = input("Enter age:")person['phone'] = input('Enter phone number:')db[pid] = persondef lookup_person(db):pid = input("Enter ID number:")fileld = input("What would you like to know?(name,age,phone)")fileld = field.strip.lower()print(fileld.capitablize() + ':', db[pid][field])def print_help():print("The available commands are:")print("store: Stores information about a person")print("lookup: Looks up a person from ID number")print("quit: Save changes and exit")print("?: Prints this message")def enter_command():cmd = input("Enter command(? for help):")cmd = cmd.strip().lower()def main():database = shelve.open("E:\\Jupyter_workspace\\study\\python\\book\\database.dat")try:while True:cmd = enter_command()if cmd == 'store':store_person(database)elif cmd == 'lookup':lookup_person(database)elif cmd == '?':print_help()elif cmd == 'quit':returnfinally:database.close()if name == '__main__':main()

re

模块re提供了对正则表达式的支持。

1,正则表达式是什么?
正则表达式是可匹配文本片段的模式。

  • 通配符
    句点与除换行符外的任何字符都匹配,被称为通配符(wildcard)。
    正则表达式’.ython‘与字符串’python’和’jython’都匹配,但不与’cpython’、'ython’等字符串匹配,因为句点只与一个字符匹配,而不与零或两个字符匹配
  • 对特殊字符进行转义
    普通字符只与自己匹配,但特殊字符的情况完全不同。
    要让特殊字符的行为与普通字符一样,可对其进行转义。
    使用模式’python\\.org’,它只与’python.org'匹配。
    为表示模块re要求的单个反斜杠,需要在字符串中书写两个反斜杠,让解释器对其进行转义。
    这里包含两层转义:解释器执行的转义和模块re执行的转义。
    也可使用原始字符串,如r'python\.org'
  • 字符集
    用方括号将一个子串括起,创建一个所谓的字符集。字符集只能匹配一个字符。
    '[pj]ython‘与’python‘和’jython'都匹配,但不与其他字符串匹配。
    '[a-z]'与a~z的任何字母都匹配。
    '[a-zA-Z0-9]'与大写字母、小写字母和数字都匹配。
    '[^abc]'与a、b和c外的其他任何字符都匹配。
  • 二选一和子模式
    python|perl’,只匹配字符串’python‘和’perl’,也可重写为’p(ython|erl)’。
    单个字符也可称为子模式
  • 可选模式和重复模式
    通过在子模式后面加上问号,可将其指定为可选的,即可包含可不包含。
    r'(http://)?(www\.)?python\.org
    只与下面这些字符串匹配:
    http://www.python.org
    http://python.org
    www.python.org
    python.org

问号表示可选的子模式可出现一次,也可不出现。
(pattern)*:pattern可重复0、1或多次。
(pattern)+:pattern可重复1或多次。
(pattern){m,n}:模式可从父m~n次。

r'w*\.python\.org'与’www.python.org‘匹配,也与’.python.org’、’ww.python.org‘和’wwwwwww.python.org‘匹配。同样,r'w+\.python\.org'与’w.python.org‘匹配,但与’.python. org‘不匹配,而r'w{3,4}\.python\.org'只与’www.python.org‘和’wwww.python.org'匹配。

  • 字符串的开头和末尾
    查找与模式匹配的子串
    字符串’www.python.org‘中的子串’www‘与模式’w+‘匹配
    确定字符串的开头是否与模式’ht+p’匹配,为此可使用脱字符(’^’)来指出这一点。
    '^ht+p‘与’http://python.org‘和’htttttp://python.org‘匹配,但与’www.http.org'不匹配。
    同样,要指定字符串末尾,可使用美元符号($)。

2,模块re的内容
模块re包含多个使用正则表达式的函数

函数描述
compile(pattern[, flags])根据包含正则表达式的字符串创建模式对象
search(pattern, string[, flags])在字符串中查找模式
match(pattern, string[, flags])在字符串开头匹配模式
split(pattern, string[, maxsplit=0])根据模式来分割字符串
findall(pattern, string)返回一个列表,其中包含字符串中所有与模式匹配的子串
sub(pat, repl, string[, count=0])将字符串中与模式pat匹配的子串都替换为repl
escape(string)对字符串中所有的正则表达式特殊字符都进行转义

函数re.compile将用字符串表示的正则表达式转换为模式对象,以提高匹配效率。

函数re.search在给定字符串中查找第一个与指定正则表达式匹配的子串。如果找到这样的子串,将返回MatchObject(结果为真),否则返回None(结果为假)。鉴于返回值的这种特征,可在条件语句中使用这个函数

import repat = "beyond"
string = "I like the beyond band"
if re.search(pat, string):print('Found it!')
#结果为:Found it!

函数re.split根据与模式匹配的子串来分割字符串。
使用re.split时,可以空格和逗号为分隔符来分割字符串。

import resome_text = 'alpha, beta,,,,gamma delta'
re.split('[, ]+', some_text)#结果为:['alpha', 'beta', 'gamma', 'delta']#如果模式包含圆括号,将在分割得到的子串之间插入括号中的内容。
re.split('o(o)','foobar')#结果为:['f', 'o', 'bar']#参数maxsplit指定最多分割多少次。
re.split('[, ]+', some_text, maxsplit=2)#结果为:['alpha', 'beta', 'gamma delta']
re.split('[, ]+', some_text, maxsplit=1)#结果为:['alpha', 'beta,,,,gamma delta']#函数re.findall返回一个列表,其中包含所有与给定模式匹配的子串。
#要找出字符串包含的所有单词
pat = '[a-zA-Z]+'
text = '"Hm... Err -- are you sure?" he said, sounding insecure.'
re.findall(pat, text)#结果为:['Hm', 'Err', 'are', 'you', 'sure', 'he', 'said', 'sounding', 'insecure']#查找所有的标点符号
pat = r'[.?\-",]+'
re.findall(pat, text)#结果为:['"', '...', '--', '?"', ',', '.']#函数re.sub从左往右将与模式匹配的子串替换为指定内容。
pat = '{name}'
text = 'Dear {name}...'
re.sub(pat, 'Mr. Gumby', text)#结果为:'Dear Mr. Gumby...'#re.escape是一个工具函数
re.escape('www.python.org')#结果为:'www\\.python\\.org'
re.escape('But where is the ambiguity?')#结果为:'But\\ where\\ is\\ the\\ ambiguity\\?'

3,匹配对象和编组
在模块re中,查找与模式匹配的子串的函数都在找到时返回MatchObject对象。
这种对象包含与模式匹配的子串的信息,还包含模式的哪部分与子串的哪部分匹配的信息。这些子串部分称为编组(group)

编组就是放在圆括号内的子模式,它们是根据左边的括号数编号的,其中编组0指的是整个模式。

’There (was a (wee) (cooper)) who (lived in Fyfe)’
包含如下编组:
0 There was a wee cooper who lived in Fyfe
1 was a wee cooper
2 wee
3 cooper
4 lived in Fyfe

r’www.(.+).com$’
编组0包含整个字符串,而编组1包含’www.‘和’.com’之间的内容。

方法描述
group([group1, …])获取与给定子模式(编组)匹配的子串
start([group])返回与给定编组匹配的子串的起始位置
end([group])返回与给定编组匹配的子串的终止位置(与切片一样,不包含终止位置)
span([group])返回与给定编组匹配的子串的起始和终止位置

方法group返回与模式中给定编组匹配的子串。如果没有指定编组号,则默认为0。
如果只指定了一个编组号(或使用默认值0),将只返回一个字符串;否则返回一个元组,其中包含与给定编组匹配的子串。
方法start返回与给定编组(默认为0,即整个模式)匹配的子串的起始索引。
方法end类似于start,但返回终止索引加1
方法span返回一个元组,其中包含与给定编组(默认为0,即整个模式)匹配的子串的起始索引和终止索引。

import re
m = re.match(r'www\.(.*)\..{3}', 'www.beyondyanyu.net')m.group(1)#结果为:4
m.end(1)#结果为:15
m.span(1)#结果为:(4,15)

4,替换中的组号和函数
将’*something*‘替换为’<em>something</em>

import re#首先开始创建模板:
emphasis_pattern = r'\*([^\*]+)\*''''
上下这两条正则表达式等价,很显然下面的加有注解很人性化。
'''emphasis_pattern = re.compile(r'''
\*      #起始突出标志---一个星号
(       #与要突出的内容匹配的编组的起始位置
[^\*]+  #与除星号外的其他字符都匹配
)       #编组到此结束
\*      #结束突出标志
''',re.VERBOSE)re.sub(emphasis_pattern, r'<em>\1</em>', 'Hello, *world*!')#结果为:'Hello, <em>world</em>!'

重复运算符默认是贪婪的,这意味着它们将匹配尽可能多的内容。

import reemphasis_pattern = r'\*(.+)\*'
re.sub(emphasis_pattern, r'<em>\1</em>', '*This* is *it*!')#结果为:'<em>This* is *it</em>!'

这个模式匹配了从第一个星号到最后一个星号的全部内容,其中包含另外两个星号!这就是贪婪的意思:能匹配多少就匹配多少。

在后面加上问号来将其指定为非贪婪

import reemphasis_pattern = r'\*\*(.+?)\*\*'
re.sub(emphasis_pattern, r'<em>\1</em>', '**This** is **it**!')#结果为:'<em>This</em> is <em>it</em>!'

5,其他有趣的标准模块

模块名称描述
argparse在UNIX中,运行命令行程序时常常需要指定各种选项(开关),Python解释器就是这样的典范。这些选项都包含在sys.argv中,但要正确地处理它们绝非容易。模块argparse使得提供功能齐备的命令行界面易如反掌。
cmd这个模块让你能够编写类似于Python交互式解释器的命令行解释器。你可定义命令,让用户能够在提示符下执行它们。或许可使用这个模块为你编写的程序提供用户界面?
csvCSV指的是逗号分隔的值(comma-seperated values),很多应用程序(如很多电子表格程序和数据库程序)都使用这种简单格式来存储表格数据。这种格式主要用于在不同的程序之间交换数据。模块csv让你能够轻松地读写CSV文件,它还以非常透明的方式处理CSV格式的一些棘手部分。
datetime如果模块time不能满足你的时间跟踪需求,模块datetime很可能能够满足。datetime支持特殊的日期和时间对象,并让你能够以各种方式创建和合并这些对象。相比于模块time,模块datetime的接口在很多方面都更加直观。
difflib这个库让你能够确定两个序列的相似程度,还让你能够从很多序列中找出与指定序列最为相似的序列。例如,可使用difflib来创建简单的搜索程序。
enum枚举类型是一种只有少数几个可能取值的类型。很多语言都内置了这样的类型,如果你在使用Python时需要这样的类型,模块enum可提供极大的帮助。
functools这个模块提供的功能是,让你能够在调用函数时只提供部分参数(部分求值,partial evaluation),以后再填充其他的参数。在Python 3.0中,这个模块包含filter和reduce。
hashlib使用这个模块可计算字符串的小型“签名”(数)。计算两个不同字符串的签名时,几乎可以肯定得到的两个签名是不同的。你可使用它来计算大型文本文件的签名,这个模块在加密和安全领域有很多用途。
itertools包含大量用于创建和合并迭代器(或其他可迭代对象)的工具,其中包括可以串接可迭代对象、创建返回无限连续整数的迭代器(类似于range,但没有上限)、反复遍历可迭代对象以及具有其他作用的函数。
logging使用print语句来确定程序中发生的情况很有用。要避免跟踪时出现大量调试输出,可将这些信息写入日志文件中。这个模块提供了一系列标准工具,可用于管理一个或多个中央日志,它还支持多种优先级不同的日志消息。
statistics计算一组数的平均值并不那么难,但是要正确地获得中位数,以确定总体标准偏差和样本标准偏差之间的差别,即便对于偶数个元素来说,也需要费点心思。在这种情况下,不要手工计算,而应使用模块statistics!
timeit模块timeit(和配套的命令行脚本)是一个测量代码段执行时间的工具。这个模块暗藏玄机,度量性能时你可能应该使用它而不是模块time。
profile模块profile(和配套模块pstats)可用于对代码段的效率进行更全面的分析。
trace模块trace可帮助你进行覆盖率分析(即代码的哪些部分执行了,哪些部分没有执行),这在编写测试代码时很有用。

小结

概念解释
模块模块基本上是一个子程序,主要作用是定义函数、类和变量等。模块包含测试代码时,应将这些代码放在一条检查name == 'main’的if语句中。如果模块位于环境变量PYTHONPATH包含的目录中,就可直接导入它;要导入存储在文件foo.py中的模块,可使用语句import foo。
包不过是包含其他模块的模块。包是使用包含文件__init__.py的目录实现的。
探索模块在交互式解释器中导入模块后,就可以众多不同的方式对其进行探索,其中包括使用dir、查看变量__all__以及使用函数help。文档和源代码也是获取信息和洞见的极佳来源。
标准库Python自带多个模块,统称为标准库。
标准库名称介绍
sys这个模块让你能够访问多个与Python解释器关系紧密的变量和函数。
os这个模块让你能够访问多个与操作系统关系紧密的变量和函数。
fileinput这个模块让你能够轻松地迭代多个文件或流的内容行。
sets、heapq和deque这三个模块提供了三种很有用的数据结构。内置类型set也实现了集合。
time这个模块让你能够获取当前时间、操作时间和日期以及设置它们的格式。
random这个模块包含用于生成随机数,从序列中随机地选择元素,以及打乱列表中元素的函数。
shelve这个模块用于创建永久性映射,其内容存储在使用给定文件名的数据库中。
re支持正则表达式的模块。

本章节介绍的新函数

函数描述
dir(obj)返回一个按字母顺序排列的属性名列表
help([obj])提供交互式帮助或有关特定对象的帮助信息
imp.reload(module)返回已导入的模块的重载版本

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Openmv通过串口接收数据、发送数据与stm32通信

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 目录 参考接线星瞳教程openmv传送数据STM32解码程序参考 接线 星瞳教程

c语言尹宝林答案,c程序设计导引 尹宝林

《C程序设计导引》特别适合作为计算机和非计算机专业学生学习高级语言程序设计的教材&#xff0c;也可供计算机等级考试者和其他各类学习者使用参考。17.40定价&#xff1a;44.75(3.89折)/2013-05-01《大学计算机优秀教材系列&#xff1a;C程序设计导引》是一本讲解C程序设计的…

第十一章 文件

第十一章 文件 打开文件 当前目录中有一个名为beyond.txt的文本文件&#xff0c;打开该文件 调用open时&#xff0c;原本可以不指定模式&#xff0c;因为其默认值就是’r’。 import io f open(beyond.txt)文件模式 值描述‘r’读取模式&#xff08;默认值&#xff09;‘w…

【TensorFlow学习笔记:神经网络八股】(实现MNIST数据集手写数字识别分类以及FASHION数据集衣裤识别分类)

课程来源&#xff1a;人工智能实践:Tensorflow笔记2 文章目录前言一、搭建网络八股sequential1.函数介绍2.6步法实现鸢尾花分类二、搭建网络八股class1.创建自己的神经网络模板&#xff1a;2.调用自己创建的model对象三、MNIST数据集1.用sequential搭建网络实现手写数字识别2.用…

第十二章 图形用户界面

第十二章 图形用户界面 GUI就是包含按钮、文本框等控件的窗口 Tkinter是事实上的Python标准GUI工具包 创建GUI示例应用程序 初探 导入tkinter import tkinter as tk也可导入这个模块的所有内容 from tkinter import *要创建GUI&#xff0c;可创建一个将充当主窗口的顶级组…

Sqlserver 2005 配置 数据库镜像:数据库镜像期间可能出现的故障:镜像超时机制

数据库镜像期间可能出现的故障 SQL Server 2005其他版本更新日期&#xff1a; 2006 年 7 月 17 日 物理故障、操作系统故障或 SQL Server 故障都可能导致数据库镜像会话失败。数据库镜像不会定期检查 Sqlservr.exe 所依赖的组件来验证组件是在正常运行还是已出现故障。但对于某…

【神经网络八股扩展】:自制数据集

课程来源&#xff1a;人工智能实践:Tensorflow笔记2 文章目录前言1、文件一览2、将load_data()函数替换掉2、调用generateds函数4、效果总结前言 本讲目标:自制数据集&#xff0c;解决本领域应用 将我们手中的图片和标签信息制作为可以直接导入的npy文件。 1、文件一览 首先看…

c语言输出11258循环,c/c++内存机制(一)(转)

一&#xff1a;C语言中的内存机制在C语言中&#xff0c;内存主要分为如下5个存储区&#xff1a;(1)栈(Stack)&#xff1a;位于函数内的局部变量(包括函数实参)&#xff0c;由编译器负责分配释放&#xff0c;函数结束&#xff0c;栈变量失效。(2)堆(Heap)&#xff1a;由程序员用…

【神经网络八股扩展】:数据增强

课程来源&#xff1a;人工智能实践:Tensorflow笔记2 文章目录前言TensorFlow2数据增强函数数据增强网络八股代码&#xff1a;总结前言 本讲目标:数据增强&#xff0c;增大数据量 关于我们为何要使用数据增强以及常用的几种数据增强的手法&#xff0c;可以看看下面的文章&#…

分享WCF聊天程序--WCFChat

无意中在一个国外的站点下到了一个利用WCF实现聊天的程序&#xff0c;作者是&#xff1a;Nikola Paljetak。研究了一下&#xff0c;自己做了测试和部分修改&#xff0c;感觉还不错&#xff0c;分享给大家。先来看下运行效果&#xff1a;开启服务&#xff1a;客户端程序&#xf…

【神经网络扩展】:断点续训和参数提取

课程来源&#xff1a;人工智能实践:Tensorflow笔记2 文章目录前言断点续训主要步骤参数提取主要步骤总结前言 本讲目标:断点续训&#xff0c;存取最优模型&#xff1b;保存可训练参数至文本 断点续训主要步骤 读取模型&#xff1a; 先定义出存放模型的路径和文件名&#xff0…

小米手环6NFC安装太空人表盘

以前看我室友峰哥、班长都有手环&#xff0c;一直想买个手环&#xff0c;不舍得&#xff0c;然后今年除夕的时候降价&#xff0c;一狠心&#xff0c;入手了&#xff0c;配上除夕的打年兽活动还有看春晚京东敲鼓领的红包和这几年攒下来的京东豆豆&#xff0c;原价279的小米手环6…

为什么两层3*3卷积核效果比1层5*5卷积核效果要好?

目录1、感受野2、2层3 * 3卷积与1层5 * 5卷积3、2层3 * 3卷积与1层5 * 5卷积的计算量比较4、2层3 * 3卷积与1层5 * 5卷积的非线性比较5、2层3 * 3卷积与1层5 * 5卷积的参数量比较1、感受野 感受野&#xff1a;卷积神经网络各输出特征像素点&#xff0c;在原始图片映射区域大小。…

算法正确性和复杂度分析

算法正确性——循环不变式 算法复杂度的计算 方法一 代换法 —局部代换 这里直接对n变量进行代换 —替换成对数或者指数的情形 n 2^m —整体代换 这里直接对递推项进行代换 —替换成内部递推下标的形式 T(2^n) S(n) 方法二 递归树法 —用实例说明 —分析每一层的内容 —除了…

第十五章 Python和Web

第十五章 Python和Web 本章讨论Python Web编程的一些方面。 三个重要的主题&#xff1a;屏幕抓取、CGI和mod_python。 屏幕抓取 屏幕抓取是通过程序下载网页并从中提取信息的过程。 下载数据并对其进行分析。 从Python Job Board&#xff08;http://python.org/jobs&#x…

【数据结构基础笔记】【图】

代码参考《妙趣横生的算法.C语言实现》 文章目录前言1、图的概念2、图的存储形式1、邻接矩阵&#xff1a;2、邻接表3、代码定义邻接表3、图的创建4、深度优先搜索DFS5、广度优先搜索BFS6、实例分析前言 本章总结&#xff1a;图的概念、图的存储形式、邻接表定义、图的创建、图…

如何蹭网

引言蹭网&#xff0c;在普通人的眼里&#xff0c;是一种很高深的技术活&#xff0c;总觉得肯定很难&#xff0c;肯定很难搞。还没开始学&#xff0c;就已经败给了自己的心里&#xff0c;其实&#xff0c;蹭网太过于简单。我可以毫不夸张的说&#xff0c;只要你会windows的基本操…

android对象缓存,Android简单实现 缓存数据

前言1、每一种要缓存的数据都是有对应的versionCode&#xff0c;通过versionCode请求网络获取是否需要更新2、提前将要缓存的数据放入assets文件夹中&#xff0c;打包上线。缓存设计代码实现/*** Created by huangbo on 2017/6/19.** 主要是缓存的工具类** 缓存设计&#xff1a…

通信原理.绪论

今天刚上通信原理的第一节课&#xff0c;没有涉及过多的讲解&#xff0c;只是讲了下大概的知识框架。现记录如下&#xff1a; 目录1、基本概念消息、信息与信号2、通信系统模型1、信息源2、发送设备3、信道4、接收设备5、信宿6、模拟通信系统模型7、数字通信系统模型8、信源编…

css rgba透明_rgba()函数以及CSS中的示例

css rgba透明Introduction: 介绍&#xff1a; Functions are used regularly while we are developing a web page or website. Therefore, to be a good developer you need to master as many functions as you can. This way your coding knowledge will increase as well …