Python学习笔记

本文详细介绍了Python编程中的各种技巧和实用工具,包括列表解析与生成器表达式、私有API、类方法和静态方法、属性拦截、异常处理、模块的使用、时间与日期操作、数据库操作、JSON序列化、测试框架、虚拟环境管理、装饰器、抽象基类与多态、函数式编程、性能分析等核心概念和方法,旨在帮助读者深入理解并熟练运用Python编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、列表解析和生成器表达式
    N=[i*2 for i in range(1,5)]为列表解析,N为一个列表对象;
    N=(i*2 for i in range(1,5))为生成器表达式,N为一个生成器的对象,它

利用了“惰性计算”的机制,在序列过长且每次只需要获取一个元素时应使用生

成器表达式。N.__next__()可获取下一个值,遍历完再用N.__next__()会抛出异

常。
2、使用下划线作为私有API的前缀,如foo是共有API,_bar是私有的。
3、类方法,在类内部定义的方法,由装饰器@classmethod来装饰,第一个参数

cls引用的就是这个类本身,调用时不用再传入参数。
4、静态方法,在类内部定义,前面通过@staticmethod来装饰,可以通过类或实

例来调用,参数随意,相当于一个普通方法。
5、类名._mro_为显示该类的继承顺序。
6、在需要私有化的属性(包括方法)前加双下划线__,无法直接通过.来访问私

有属性,可通过调用非私有方法(此方法中调用私有方法)来访问;用

@property装饰一个函数foo(self),返回某个私有属性,就可通过类.foo来访问

私有属性。
7、运算符之所以可以使用是因为进行运算的类有相应的特殊方法,比如

__add__,__sub__,__mul__,__div__。
8,使用__slots__特殊属性可以将__dict__挤出去,增加实例时,实例的

__slots__并不增加,通过类定义的属性都是只读的,__slots__可以提升对实例

属性的操作速度。
9、__setattr__(self , name , value)给name赋值时调用该方法。
__getattr__(self , name)访问name而name不存在时调用它;
__getattribute__(self , name)访问name时被调用,不管存在与否,return时

注意不要使用return self.__dict__[name],否则会无限循环调用

__getattribute__,应使用return object.__getattribute__(self,name)。
以上三种方法被称为属性拦截,可避免一些报错。
10、一个函数,只要包含了yield,就是生成器,生成器就是对象;直接调用生

成器不会执行函数体内语句,将调用后的函数引用传给一个变量,使用

__next__()则会开始执行函数,遇到yield会返回值,并暂停,下次再调用则从

暂停位置开始继续执行,没有满足条件的值后则会抛出StopIteration异常。
可以通过inspect.isgeneratorfunction()检查一个函数是否是生成器;

inspect.getgeneratorstate()可以查看生成器当前状态,

GEN_CREATED,GEN_RUNNING(正在被解析器执行),GEN_SUSPENDED(等待被唤醒调

用),GEN_CLOSED;
11、捕捉异常时用try: except: else: finally:,若无异常,则会执行try和

else里的语句,若有异常,则执行except的语句,finally语句总是会被执行。
12、assert断言,可用assert expression, "xxx"若表达式不为真,则输

出"xxx" 其异常类型为AssertionError,可用try,except语句接收。
13、导入一个自定义的模块,需要先import sys,然后sys.path.append('模块

的路径'),然后可以导入,这种方式当关闭当前terminal时会失效,可设置

PYTHONPATH环境变量:export PYTHONPATH=$PYTHONPATH:路径;属性__name__是

模块的名称。
14、模块中的私有变量不能直接访问,可通过模块.变量来访问,__all__属性是

一个列表,其中包含了可被访问的变量名,无论是否私有,不在该列表里的变量

无法被访问(通过from xx import *导入的就是__all__里面的方法)。
15、在一个包中增加一个名为__init__.py的空文件,就可以将该目录中的其

他.py文件作为模块被引用。
16、模块的__doc__属性是模块的文档,位于模块文件的开始注释处,__file__

属性是该模块的位置。
17、sys.argv是向Python解释器传递参数的,如$python a b c d ,sys.argv

[0]就是a。
18、os模块,os.rename(原文件名,新文件名),可重命名文件或目录,

os.remove(文件名),不能用来删除目录;os.listdir(目录),显示目录中的内

容到一个列表中;os.getcwd()获取当前路径,os.chdir(路径)改变当前路径,

os.pardir()上一级目录;os.removedirs(dir),删除目录,该目录必须为空,

os.makedirs(dir),新建目录,可以级联新建,而os.mkdir()不可以;
os.stat(dir)可查看目录或文件的信息。
os.system(xxx)xxx为操作系统的命令,这样可在Python中使用操作系统命令。
19、shutil模块的rmtree(dir)方法可以删除不为空的目录。
20、import webbrowser   webbrowser.open("http://www.xxx.com")可打开网

页。
21、最上面是最小值的是最小堆(父节点总小于等于子节点),最上面是最大值

的是最大堆(父节点总大于等于子节点)。
22、堆,heapq模块,heap使用列表存储数据,里面不仅可以放数字;

heapq.heappush(heap,x),往二叉树里增加值,并按照二叉树的结构进行存储(

最小堆);heapq.heappop(heap),从堆中删除一个最小元素并返回;

heapq.heapify(list),将一个列表转化为最小堆,改变了list而不是新生成一个

对象;heapq.heapreplace(heap,x),是heappop和heappop的结合,删掉最小的一

个并加入一个新值x。
23、collections模块中包括许多有用的数据结构;比如depue,双端队列,先

a=depue(list),将list转化为depue对象,然后a.append(x),从右边增加值,

a.appendleft(b),从左边增加;a.pop()删除最后一个元素,a.popleft()删除第

一个元素;a.rotate(i)表示将a中的元素首尾连接起来,像一个圆,元素顺时针

排列,i表示每个元素按顺时针方向前进i个位置,若i为负数,则逆时针旋转,

该函数改变了这个depue对象。
24、calendar模块,calendar.month(year,month,w=2,l=1)显示月历;

calendar.calendar(year,w=2,l=1,c=6)返回year年的年历,三个月一行,间隔

距离为c,每日宽度间隔为w字符,每行的长度为21*w+18+2*c,l为每星期的行数


calendar.isleap(year)判断是否为闰年,是返回True,不是返回False;
calendar.leapdays(y1,y2)返回两年之间的闰年总数,包括y1不包括y2(像是切

片);
calendar.monthcalendar(year,month)返回一个列表,列表中的元素还是列表,

每一个子列表都是该月份的每个星期的日期,从周一到周日,如果没有本月的则

为0;
calendar.monthrange(year,month)返回一个元组,里面有两个整数,第一个是

该月从周几开始,0代表周一,6代表周日,第二个代表这个月有多少天;
calendar.weekday(year,month,day)返回是周几,0为周一,6为周日。
25、time模块;
time.time(),获取当前时间戳,从1970年1月1日0时0分0秒开始到当前的总秒数

(不包括闰秒);
time.localtime() 得到time.struct_time(tm_year=2015,

tm_mon=5,tm_mday=4,tm_hour=20,tm_min=33,tm_sec=39,tm_wday=1,tm_yday=12

4,tm_isdat=0)其中tm_wday是一周中的第几天,tm_yday是一年中的第几天,

tm_isdst是否为夏令时,该函数的默认参数为time.time(),参数为时间戳;
time.gmtime()得到的是格林尼治时间;
time.asctime() 得到 'weekday month day hour:min:sec year'该函数默认以

time.localtime()的值作为参数,参数必须为时间元组;
time.ctime()得到的结果与上面一样,只是它的参数为time.time()也就是时间

戳;
time.mktime(),将时间元组转化为时间戳;
time.strftime(format[,tuple]),将时间元组按照指定格式转化为字符串,不指

定则默认为localtime()的值,格式可指定年份(可去掉世纪)、月份(英文

全称或简写或数字)、一年中的第几天、该月的第几日、小时(24或12制)、分

钟、秒钟、该年的第几周(周日为起点或周一为起点)、周几、时区、日期(日

/月/年)、时间(时:分:秒)、日期时间(年月日时分秒)、%字符、上下午;
time.strptime(str,format)将字符串转化为时间元组,格式同上;
26、datetime模块;
datetime.date类,日期类,有year、month、day属性,today()方法得到今天日

期、ctime()方法、timetuple()方法、toordinal()方法得到时间戳,

fromordinal(to)将时间戳转化为格式化时间,replace

(year=xx,month=xx,day=xx)可改变日期对象;
datetime.time类,初始化函数(hour,min,sec),有hour、minute、second、

microsecond、tzinfo属性;
datetime.timedelta类,主要用来做时间的运算;now=datetime.datetime.now

(),b=now+datetime.timedelta(weeks=2,hours=5),增加时间。
27、XML相关模块,xml用来传输数据,而不是显示数据;
xml.dom.*   xml.sax.*  xml.parser.expat各有缺点,使用

xml.etree.ElementTree(元素树);
import xml.etree.ElementTree as ET
t=ET.ElementTree(file="xx.xml")  建立起xml解析树对象
root=t.getroot()  获得根
root.tag 根的标签  root.attrib 根的属性
for child in root:
    print(child.tag, child.attrib)   将根下面的元素都读取出来(一层)
或:
root[0].tag  root[0].attrib root[0].text查看文本
root[0][0]查看下一层的内容;
t.iter(tag="xx"),对指定名称的子节点进行深度优先遍历,可用for循环显示,

若不指定元素,则全部遍历;也可通过t.iterfind("xx/xx")搜索指定元素并读

取内容;利用t.findall("xx")也可实现查找功能;
编辑xml文件:del root[i] 删除,之后使用t.write(路径)保存才可生效;标签

.set("属性","值")可以在标签里增加属性;root.remove(标签)使用较多;

ET.SubElement(root,"xx")在root里面增加book节点;
28、JSON,一种轻量级的数据交换格式;JSON模块主要执行序列化或反序列化功

能;序列化就是讲Python对象编码转化为JSON字符串,反之亦然;
json.dumps(xx,sort_keys=True,indent=2),序列化,返回字符串对象,并将其

中元组变成了列表,后面两个参数可不写,可按照字典顺序排列并缩进,增加可

读性;
json.loads(xx),decoding,并不会将列表还原为元组;
数据太大可用tempfile的NamedTemporaryFile方法来处理;
29、在python的site-packages目录可以删除第三方库文件来卸载;
30、requests库,r=requests.get("www.xxx.com")
r.cookies  r.headers r.encoding   r.ststus_code   r.text  r.content
requests.post("www.xxx.com",data=xx)
31、pickle模块,pickle.dump(xx,f),将数据保存到了文件里,这成为将对象

序列化,pickle.dump(obj,file[,protocol]),obj可以是自定义类型的对象。
pickle.load(file),反序列化,可以读取文件中的数据。
32、shelve模块,s=shelve.open("file"),s['x']=" aa",类似字典,可称之为

类字典对象,若要更改已有键值,需要shelve.open("file",writeback=True)才

可修改。
33、PyMySql是python操作数据库的模块,也被称为借口程序,好比一把钥匙,它

是在mysql的外面操作数据库,不需要进入mysql的交互模式。

conn=pymysql.connect(host,port,user,passwd,db,charset,...)得到连接对象

,可以进行提交(commit()),回滚(rollback()),返回连接的游标对象

(cursor([cursorclass])),关闭连接(close())的操作;
Python通过游标执行SQL语句,所以要得到游标对象,cur=conn.cursor

(),cur=conn.cursor(pymysql.cursors.DictCursor)可以将读取到的数据变为字

典形式,游标对象有关闭(close())、执行一条(execute(query[,args]))或对

序列中每个参数(executemany(query,pseq))执行SQL语句,返回一条(fetchone

())或所有(fetchall())或若干条(fetchmany([size]))查询结果,移动到下一个

结果(nextset()),移动游标到指定行(scroll

(value,mode='relative'/'absolute'))等操作。
34、NoSQL,Not Only SQL,非关系型数据库,MongoDB是NoSQL其一;db是一个

全局变量,哪个数据库正在使用就作为对象赋给db,MongoDB的基本单元是文档

,类似字典;数据库里有集合,集合里面有文档,这就是MOngoDB的结构,它是

“随用,随取,随建立”的用法,不用特意create;
pymongo模块,是MongoDB的驱动模块;通过client=pymongo.MongoClient

('localhost',27017)建立连接;db=client.mydb,获取数据库对象,

db.collection_names()获取集合的名字,再通过a=db.集合名获取集合对象就可

操作里面内容。a.find_one()可以查看集合中信息,加入参数还可以查询满足条

件的文档,a.insert(dict)在集合中新增一个文档,或者a.insert

([dict,dict,dict])实现批量插入,a.find()返回可迭代对象,包含集合中所有

文档,a.find().count()查看文档个数;a.find().sort("字段",

pymongo.ASCENDING)升序,pymongo.DESCEDING降序;
a.update({"xx":"xx"},{"$set":{"aa":"bb"}})前面是要更新的文档的条件,后

面是$set加要更新的内容,$unset是完全删除某个键,$inc是增加已有键的值(

整数、长整数、双精度浮点数),没有则创建,$push操作数组,在末尾增加一

个元素,不存在则创建一个数组;
a.remove(条件),按照条件删除整个文档;
a.create_index([("xx",pymongo.DESCENDING),])建立索引;
35、SQLite,一个小型的关系型数据库,无需安装,驱动模块也已经内置;操作

和MySQL类似,都需要建立连接,然后建立游标对象;可以使用SQL语句;
36、Python中文档的格式是reStructuredText,一种轻量级的标记语言,Sphinx

是处理reST最常用的工具;
在conf.py中添加:
extensions=['xx'],xx为sphinx.ext.autodoc时可以从模块中抽取rest格式的文

档字符串并生成.rst文件;sphinx.ext.autosummary启动sphinx.ext.autogen模

块,然后在一个.rst中加入:
.. autosummary::


   mymodule
   mymodule.submodule
可为特定模块生成TOC,这回生成名为generated/mymodule.rst和

generated/mymodule.submodule.rst的文件,包含autodoc指令;
36、Sphinx可在生成文档时自动在例子上运行doctest,它能针对代码片段搜索

文档并运行代码以测试是否反映其实际行为;sphinx-build -b doctest

doc/source doc/build
Sphinx还可以用于:  项目间使用的链接;HTML主题,图表和公式;输出为

Texinfo( Texinfo是一个文档系统,可用于创建PDF、HTML等文档)和EPUB格式

(EPUB(Electronic Publication 的缩写,电子出版)是一种电子图书标准,

其中包括 3 种文件格式标准(文件的附文件名为 .epub));链接到外部文档


Sphinx支持多种语言,不只是Python;
Sphinx 使用 reStructuredText 标记语法(和其他一些语法)来提供文档控制


37、restructuredtext语法简介:

重点、解释文字,重点(emphasis)通常显示为斜体

重点强调(strong emphasis)通常显示为粗体

行内文本(inline literal)通常显示为等宽文本,空格可以保留,但是换行不可

以。

章节头部由下线(也可有上线)和包含标点的标题 组合创建, 其中下线要至少等

于标准文本的长度。
可以表示标题的符号有 =、-、`、:、'、"、~、^、_ 、* 、+、 #、<、> 。
对于相同的符号,有上标是一级标题,没有上标是二级标题。
标题最多分六级,可以自由组合使用。
全加上上标或者是全不加上标,使用不同的 6 个符号的标题依次排列,则会依

次生成的标题为H1-H6。

段落是被空行分割的文字片段,左侧必须对齐(没有空格,或者有相同多的空格

)。缩进的段落被视为引文。

符号列表可以使用 -、*、+ 来表示。
不同的符号结尾需要加上空行,下级列表需要有空格缩进。

枚举列表算即顺序(序号)列表,可以使用不同的枚举序号来表示列表。
可以使用的枚举有:
阿拉伯数字: 1, 2, 3, ... (无上限)。
大写字母: A-Z。
小写字母: a-z。
大写罗马数字: I, II, III, IV, ..., MMMMCMXCIX (4999)。
小写罗马数字: i, ii, iii, iv, ..., mmmmcmxcix (4999)。

可以为序号添加前缀和后缀,下面的是被允许的。
. 后缀: "1.", "A.", "a.", "I.", "i."。
() 包起来: "(1)", "(A)", "(a)", "(I)", "(i)"。
) 后缀: "1)", "A)", "a)", "I)", "i)"。
枚举列表可以结合 # 自动生成枚举序号。

定义列表可以理解为解释列表,即名词解释。
条目占一行,解释文本要有缩进;多层可根据缩进实现。

字段列表
:标题: reStructuredText语法说明

:作者:
 - Seay
 - Seay1
 - Seay2

:时间: 2016年06月21日

:概述: 这是一篇
 关于reStructuredText

 语法说明。

选项列表是一个类似两列的表格,左边是参数,右边是描述信息。当参数选项过

长时,参数选项和描述信息各占一行。
选项与参数之间有一个空格,参数选项与描述信息之间至少有两个空格。

文字块就是一段文字信息,在需要插入文本块的段落后面加上 ::,接着一个空

行,然后就是文字块了。

文字块不能定顶头写,要有缩进,结束标志是,新的一段文本贴开头,即没有缩

进。

行块对于地址、诗句以及无装饰列表是非常有用的。行块是以 | 开头,每一个

行块可以是多段文本。| 前后各有一个空格。

块引用是通过缩进来实现的,引用块要在前面的段落基础上缩进。
通常引用结尾会加上出处(attribution),出处的文字块开头是 --、--- 、—,

后面加上出处信息。
块引用可以使用空的注释 .. 分隔上下的块引用。
注意在新的块和出处都要添加一个空行。

文档测试块是交互式的Python会话,以 >>> 开始,一个空行结束。

reStructuredText提供两种表格:网格表(Grid Tables),简单表(Simple

Tables)。
网格表中使用的符号有:-、=、|、+。
- 用来分隔行, = 用来分隔表头和表体行,| 用来分隔列,+ 用来表示行和列

相交的节点。
简单表相对于网格表,少了 | 和 + 两个符号,只用 - 和 = 表示。

分隔符就是一条水平的横线,是由 4 个 - 或者更多组成,需要添加换行。

reStructuredText会自动将网址生成超链接。

引用/参考(reference),是简单的形式,只能是一个词语,引用的文字不能带有

空格
引用/参考(reference),行内形式,引用的文字可以带有空格或者符号。

内部超链接:
更多信息参考 引用文档_

这里是其他内容

.. _引用文档:

这是引用部分的内容

匿名超链接,词组(短语)引用/参考(phrase reference),引用的文字可以带有

空格或者符号,需要使用反引号引起来。

间接超链接,间接超链接是基于匿名链接的基础上的,就是将匿名链接地址换成

了外部引用名_。

隐式超链接,小节标题、脚注和引用参考会自动生成超链接地址,使用小节标题

、脚注或引用参考名称作为超链接名称就可以生成隐式链接。

替换引用就是用定义的指令替换对应的文字或图片,和内置指令(inline

directives)类似。
这是 |logo| github的Logo,我的github用户名是:|name|。

.. |logo| image::

https://help.github.com/assets/images/site/favicon.ico
.. |name| replace:: SeayXu

脚注引用,有这几个方式:有手工序号(标记序号123之类)、自动序号(填入#号

会自动填充序号)、自动符号(填入*会自动生成符号)。
手工序号可以和#结合使用,会自动延续手工的序号。
# 表示的方法可以在后面加上一个名称,这个名称就会生成一个链接。

引用参考与上面的脚注有点类似。
引用参考的内容通常放在页面结尾处,比如 [One]_,Two_
.. [One] 参考引用一
.. [Two] 参考引用二

注释以 .. 开头,后面接注释内容即可,可以是多行内容,多行时每行开头要加

一个空格。


38、distutils,是Python标准库的一部分,可以导入之后通过合适的命令运行

setup即可生成setup.py;setuptools也是标准库中的软件打包的一种方式;目前

,setuptools是分发库的主要选择,在未来要对distlib保持关注;
pbr,指Python Build Reasonableness,可基于requirements.txt做自动依赖安

装,利用Sphinx实现文档自动化,基于git history自动生成AUTHORS和

ChangeLog文件等;
Wheel格式,是针对Python的分发包定义的新的标准,工具也命名为wheel;
python setup.py bdist_wheel这条命令将在dist目录中创建.whl文件,和Egg类

似,一个Wheel归档文件就是一个有着不同扩展名的压缩文件,只是无需安装,

只要在包后面加一个斜杠加载和运行代码;
可以直接python xxx.zip来运行压缩文件,这等于PYTHONPATH=xxx.zip python

-m __main__;或者python xxx.zip/mymod 这等于PYTHONPATH=xxx.zip python

-m mymod.__main__;

39、PyPI(Python Package Index)是python官方的第三方库的仓库,所有人都可

以下载第三方库或上传自己开发的库到PyPI。PyPI推荐使用pip包管理器来下载

第三方库。

40、相比于easy_install,pip项目提供了良好的安装包的方式,只需要pip

install xx即可从PyPI、tarball、Wheel归档中安装或卸载包;
也可以通过--user选项让pip将包安装在home目录中,可避免在系统层面安装;

若要避免多次重复下载包,可以将环境变量PIP_DOWNLOAD_CACHE指向一个目录,

pip就用它来保存下载的tarball,也可以在~/.p.p/pip.conf文件中添加

download-cache选项;

41、要看到一个包中可用的入口点可以使用一个叫entry_point_inspector的包

,安装后,它提供了名为epi的命令;运行epi group list,显示系统有很多不同

的包都提供了入口点;使用epi group show xxx查看某个具体的入口点;使用

kepi ep show xxx xx可以获得更多信息,可以看到模块、成员、包、路径等信

息;

42、开发Python应用程序时,会提供一个可启动的程序,也就是一个可运行的

Python脚本
可使用pip freeze列出当前已安装的包;

使用setup.py sdist,这会在源代码树的dist母驴下创建一个tarball,用来安

装软件;

可以使用pkg_resources从自己的Python程序中发现和加载入口点文件;
stevedore基于和pkg_resources类似的机制提供了对动态插件的支持

43、为了解决由于环境的变更导致的应用程序无法运行,针对每个应用程序使用

独立的库目录,然后使用这个目录而不是系统安装的目录来加载所需的模块;工

具virtualenv可以自动处理这些目录;它会创建lib/pythonX.Y目录,并用它安

装setuptools和pip,以便安装其他Python包;可以通过source

myvenv/bin/activate来激活这个虚拟环境,这么做之后,shell的提示符会加上

虚拟环境的名字作为前缀,调用python会执行被复制到虚拟环境中的python,可

以通过deactivate来停止并退出虚拟环境;
venv模块是标准库的一部分,可以操作虚拟环境而无需使用virtualenv包,可通

过Python的-m标志来加载模块,python -m venv myvenv;


44、测试应该保存在应用程序或库的tests子模块中,代码mylib/foobar.py的测

试应该存储在mylib/tests/test_foobar.py中;
nose包,将提供nosetests命令,会加载所有以test_开头的文件,然后执行其中

所有以test_开头的函数;有异常抛出,测试就会出错退出;
实现一些高级的测试可以使用unittest,它是标准库的一部分;需要创建一个继

承了unittest.TestCase的类,并在里面写一个运行测试的方法,里面不使用

assert,而是assertEqual()来做等价的测试器;
写测试用例时永远不应该使用assert;
unittest还提供了一组测试函数,可以用作特化测试;fail(msg)可以让某个测

试立即失败并返回信息;可以使用unittest.TestCase.skipTest(msg)、

unittest.skip()装饰器、unittest.skipIf(xx,"aa")装饰器来忽略某个测试;
python -m unittest -v test_foo可以用来运行特定的测试模块;
unittest提供了两个特殊的方法setUp和tearDown,他们会在类的每个测试方法

调用前后执行一次;

45、在单元测试里,fixtures表示“测试前创建,测试后销毁”的组件;
fixtures模块(不是标准库的一部分)提供了一种简单的创建fixture类和对象

的机制;fixtures.EnvironmentVariable,对于在os.environ中添加或修改变量

很有用,并且这些变量会在测试退出后重置;

46、mock对象就是模拟对象,用来作为测试环境对代码进行测试;标准库中用来

创建mock对象的库名为mock,可以用来模拟一系列动作,还可以传一个mock对象

到代码的任何部分,并在其后检查代码是否按其期望的传入参数被调用,可以用

mock.ANY作为参数值传入,会匹配传递给mock方法的任何参数。也可以使用

mock.patch的装饰器版本;使用模拟可以很方便的模拟任何问题;

47、testscenarios包,提供了一种简单的方式针对一组实时生成的不同场景运

行类测试;写的类继承自testscenarios.TestWithScenarios(这个类继承自

unittest.TestCase),构建一个场景列表,我们需要一个元组列表,其将场景名

称作为第一个参数,将针对此场景的属性字典作为第二个参数;

48、subunit是用来为测试结果提供流协议的一个模块,它可以聚合测试结果或

对测试的运行记录或归档;python -m subunit.run test_scenario就可以运行

测试,这输出的是二进制数据,python -m subunit.run test_scenario |

subunit2pyunit可以将结果转化为易读模式;还有subunit2csv、subunit2gtk、

subunit2junitxml等工具;可以传入discover参数自动发现哪个测试要运行,也

可以通过传入参数--list只列出测试但不运行,可以使用--load-list指定要运

行的测试的清单而不是运行所有的测试;
testrepository包提供了testr程序,可以用来处理要运行的测试数据库;一旦

subunit的测试流被运行并加载到testrepository,就可以很容易用testr命令来

操作。可以通过编辑项目的根目录中的.testr.conf文件来“教会”testr如何执

行要运行的测试,可以编写执行testr run时要执行的命令,加载测试列表要运

行的命令,列出测试列表要运行的命令。另外,给testr run加上--prallel选项

即可实现测试的并行执行,可以设置--concurrency=int进程的数目;

49、coverage模块,测试覆盖,它通过分析工具来判断代码的哪些部分被执行了

;使用nosetests --with-cover就可以生成一份代码覆盖报告,加上--cover-

package=xx可以指定包,不用看到每个被用到的python包,加上--cover-html标

志可以生成html报表;使用testrepository是,可以使用setuptools集成运行

coverage:python setup.py testr --coverage,这样可以介个coverage自动运

行测试集,并在cover目录下生成html报告;

50、tox的目标是自动化和标准化Python中运行测试的方式,它提供了在一个干

净的虚拟环境中运行整个测试集的所有功能;使用tox之前,需要创建一个

tox.ini,放在被测试项目的根目录,与setup.py同级。
运行tox之后,编辑tox.ini,在[testenv](定义的是被tox管理的所有虚拟环境

参数) 下增加deps=nose
 commands=nosetests,若在使用pbr管理setup.py文件,则可在下面添加-

rrequirements.txt,以读取所有依赖;可以使用tox -e pyxx来指定模拟python

的版本,也可以在配置文件里针对不同的环境运行不同的命令;配置文件里可用

[tox] envlist=pyxx,pyxx来支持多个版本,也可以使用tox来继承其他测试,如

flake8:[testenv:pep8] deps=flake8 commands=flake8;


51、装饰器本质上就是一个函数,这个函数接收其他函数作为参数,并将其以一

个新的修改后的函数进行替换;使用原生的实现装饰器的方法会导致新的函数缺

少docstring(文档)和名字,可以通过functools模块来解决;
可以调用f=functools.update_wrapper(装饰器函数,被装饰函数)来手动进行装

饰,即可复制原函数的名字和文档;它还提供了名为wraps的装饰器,在装饰函

数定义的下面加上@functools.wraps(f)即可;
inspect模块可以更加智能提取函数的签名并对其进行操作;在装饰函数的内层

函数里使用func_args=inspect.getcallargs(f,*args,**kwargs),它返回一个将

参数名字和值作为键值对的字典,可以方便查找;

52、方法是指作为类属性保存的函数,Python3中可以通过类直接调用方法,只

要传入任何包含方法期望属性的对象即可;有了对方法的引用,但想知道它被绑

定到了哪个对象,可以查看方法的__self__属性;
静态方法@staticmethod不依赖于对象的状态,可以在子类中覆盖静态方法,它

的参数不作固定要求;
类方法@classmethod是直接绑定到类而非它的实例的方法,它的第一个参数是类

本身cls;
抽象方法,定义在积累中可能有或没有任何实现的方法,任何继承它的子类都需

要实现并重写抽象方法,否则调用方法是会引发异常;
使用内置的abc模块实现抽象方法,在方法前加__metaclass__ = abc.ABCMeta
@abc.abstractmethod  ,则当实例化它或未重写该方法的子类时会报错;
在实现抽象方法时可以对方法的参数进行扩展,而且可将其实现为静态方法或类

方法;可以在@abc.abstractmethod 之上使用@staticmethod或@classmethod,

但不会强迫其子类也将其定义为类或静态方法;在抽象方法中也可以有实现代码

,并且子类可以通过super(子类,self).f()来调用;

53、类继承时除了直接指定也可以返回一个表达式,只要结果是一个对象;
通过两个参数调用super会得到绑定的super对象,可以访问类属性;若只用一个

参数调用super(),则会返回一个未绑定的super对象,可以通过__get__()方

法啊来找到属性;python3中可以不传参数给super(),它可以自动搜索栈框架



54、函数式编程特点:可形式化证明,模块化,简洁,并发,可测性;all

(iterable)和any(iterable)可以判断这个可迭代对象中的任何值或是否有值满

足条件;first模块中的first函数,可以判断并返回第一个满足条件的值;
functools.partial,key=partial(func,arg=a),它修改收到的参数而不是函数

的行为,也就是说,可以写一个函数并利用functools.partial根据需要针对给

定的某个场景进行自定义;
operator模块,operator.le(a,b),接收两个数并返回第一个数是否小于等于第

二个数,可用在functools.partial中;
itertools模块提供了一组很有用的函数,和operator模块组合在一起特别有用

,可以覆盖大部分使用lambda的情况;

55、ast模块可以解析一段python代码并将其转储从而生成抽象语法树;

ast.parse()函数返回一个_ast.Module对象,作为树的根,这个根可以通过

ast.dump()整个转储;Module(body=[Assign(targets=[Name

(id='x',ctx=Store())],value=Num(n=42))]),在body中包含一组待求值的语句

或表达式,通常表示这个文件的内容;科通过ast.Str,ast.Print来获得内容,

ast.Module(body=[])获取module,compile()编译module,最后通过eval()

执行语句;抽象语法树中可用的完整对象列表可通过阅读_ast模块的文档获得;

语句和表达式,语句继承自ast.stmt,表达式继承自ast.expr,ast.operator用

来定义标准的运算符(+、/...),ast.copop来定义比较运算符;

56、Hy对提供的代码进行解析并编译成Python抽象语法树;可以直接导入任何

Python库到Hy中并随意使用;

57、数据结构,collections.defaultdict(fun),每次试图从字典中访问一个不

存在的元素,defaultdict都会使用作为参数传入的这个函数去构造一个新值而

不是抛出KeyError;还有OrderedDict或者Counter等有用的数据结构;

58、性能分析,使用cProfile对程序进行性能分析,python -m cProfile

xxx.py可以显示性能信息;python -m cProfile -o xx.cprof xxx.py保存性能

分析数据,pyprof2calltree -k -i xx.cprof可以可视化性能分析数据;使用

dis模块的dis.dis()函数可以反编译作为参数传入的函数,并打印出这个函数运

行的字节码指令清单,可以从细微处优化代码;无理由的嵌套函数会使效率下降

;唯一需要在函数内定义函数的场景是在构建函数闭包的时候;

59、有序列表的元素获取时间为O(log n);
bisect模块,其中包含了二分查找算法,Bisect模块提供的函数有:
bisect.bisect_left(a,x, lo=0, hi=len(a)) :查找在有序列表 a 中插入 x 的

index。lo 和 hi 用于指定列表的区间,默认是使用整个列表。如果 x 已经存

在,在其左边插入。返回值为 index。
bisect.bisect_right(a,x, lo=0, hi=len(a))
bisect.bisect(a, x,lo=0, hi=len(a)) :
这2个函数和 bisect_left 类似,但如果 x 已经存在,在其右边插入。
bisect.insort_left(a,x, lo=0, hi=len(a)) :
在有序列表 a 中插入 x。和 a.insert(bisect.bisect_left(a,x, lo, hi), x)

的效果相同。
bisect.insort_right(a,x, lo=0, hi=len(a))
bisect.insort(a, x,lo=0, hi=len(a)) :
和 insort_left 类似,但如果 x 已经存在,在其右边插入。

此外还有更多的数据结构,如二叉树和红黑树,包blist和bintree就包含了,不

要开发自己的版本。
可以通过python -m memory_profiler xx.py查看内存的使用情况。

60、collections模块中的namedtuple类,它允许动态创建一个继承自tuple的类

,它可以通过命名属性获取元组的元素而不是通过索引;还提供了一些额外的方

法,_asdict可将namedtuple转换为字典实例,_make可以转换已有的iterable对

象为namedtuple,_replace替换某些自断后返回一个该对象的新实例。

61、menoization是指通过缓存函数返回结果来加速函数调用的一种技术;

functools模块提供了一个LRU缓存装饰器,还提供了对缓存命中、缺失等的统计

,在用来缓存的函数前面加上@functools.lru_cache(maxsize=n),用

f.cache_info()可以查看缓存的信息;

62、PyPy的目的是要用Python写一个Python解释器;是符合标准的Python语言的

一个高效实现;

63、memory_profiler是一个不错的python包,可以用来逐行查看程序的内存使

用情况。可以使用实现了缓冲区协议的对象,对于实现了该协议的对象,可以使

用memoryview类的构建函数去构造一个新的memoryview对象,它会引用原始的对

象内存,可以减少复制整个对象的内存开销;array模块中的独享以及struct模

块中的函数都能正确的处理缓冲区协议,因此在需要零复制时都能高效完成。

64、多线程,是在一个Python进程中将代码运行在不同的处理器上的能力,意味

着代码的不同部分可以并行执行;GIL指全局解释锁(Global Interpreter Lock

);因为GIL的问题,多线程并非好的可扩展性方案,更好的方案是Python中提

供的multiprocessing包,它会启动一个新的进程;pool=mutiprocessing.Pool

(num)开启8个进程,pool.map(fun,range(n))运行某个函数n次;还可以通过

multiprocessing.managers对象在网络中分散负载;

65、使用事件驱动方法对于监听数百个事件源的场景的效果要好于为每个事件创

建一个线程的方式;select模块,可以用来构造一个事件驱动系统。程序会调用

一个函数,它会一直阻塞直到收到事件;

66、SOA(Service-Oriented Architecture)面向服务架构,是Openstack所有

组件都在使用的架构;使用传输总线(transport bus)解耦应用是一个好的选

择,允许建立同步和异步API,从而轻松的实现扩展。

67、RDBMS(关系型数据库管理系统),ORM(对象关系映射)。

68、有了单元测试并配置了yox后,就可以通过tox -e py27,py33进行测试,直

到所有测试都通过为止;

69、使用six来处理python2到python3的兼容问题(2*3=6);

70、with open('file','r') as f:   open()返回的对象有两个方法,一个是

__enter__, 另一个是__exit__,他们分别在with块开始和结束时被调用;

contextlib标准库中提供了contextmanager,通过生成器构造这两个方法,在生

成器前加上@contextlib.contextmanager;在某些情况下,同时使用多个上下文

管理器是很有用的,例如,同时打开两个文件以复制他们的内容,用一条with同

时打开两个文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值