- 浏览: 63744 次
- 性别:
- 来自: 广东省惠州市
最新评论
-
wl6179:
很不一样的视角,谢谢yzjklove的解说!
Python学习笔记(实用技巧) -
wl6179:
貌似不错哦,如能上传一张效果图就完美了~
在Django中实现验证码 -
wl6179:
谢谢,受教了!
[Django学习]事务处理 -
fire01312:
这个不错!
如何根据已有数据自动产生Model
1. 编程 FAQ
- Date: $Date: 2005-06-05 19:37:51 -0500 (Sun, 05 Jun 2005) $ Version: $Revision: 8226 $ Web site:
1.1. 一般问题
1.1.1. 是否有源码级的调试器, 具有breakpoint, single-stepping等功能?
是的。
pdb模块是一个简单却强大的命令行模式的python调试器。它是标准python库的一部分, 在库参考手册中有关于它的文档。作为一个例 子,你也可以使用pdb的代码编写你自己的调试器。
作为标准python发行包的一部分(通常为Tools/scripts/idle),IDLE包含了一个图形界面的调试器。在http://www.python.org/idle/doc/idle2.html#Debugger有IDLE调试器的文档。
另一个Python IDE,PythonWin包含了一个基于pdb的GUI调试器。 Pythonwin调试器对breakpoints作颜色标记,它还有一些很酷的特性,比如调试非python程序。可以参考http://www.python.org/windows/pythonwin/。最 新版本的PythonWin已作为ActivePython 发行包的一部分(见 http://www.activestate.com/Products/ActivePython/index.html)。
Boa Constructor 是一个使用wxPython的IDE和GUI builder。它提供了可视化的框架创建和操作,一个对象探查器,多种代码视图比如对象浏览器,继承架构,doc string创建的html文档,一个高级调试器,继承帮助和Zope支持。
Eric3 是基于PyQt和Scintilla editing组件的一个IDE。
Pydb是python标准调试器pdb的一个版本, 与DDD(Data Display Debugger, 一个流行的调试器图形界面)一起工作。Pydb 可以在http://packages.debian.org/unstable/devel/pydb.html找到,DDD可以在 http://www.gnu.org/software/ddd找到.
还有很多包含图形界面的商业版本Python IDE。包括:
-
Wing IDE (http://wingide.com)
-
Komodo IDE (http://www.activestate.com/Products/Komodo)
1.1.2. 是否有工具可以帮助找到bug或者做静态分析?
是的.
PyChecker是一个静态分析器,它可以找出python代码中的bug并对代码的复杂性和风格作出警告。可以在 http://pychecker.sf.net找到它.
另一个工具Pylint 检查一个模块是否满足编码规范,它还支持插件扩展。除了PyChecker能提供的bug检查外,Pylint 还提供额外的特性比如检查代码行长度,变量名是否符合代码规范,声明的接口是否都已实现等。http://www.logilab.org/projects/pylint/documentation 提供了关于Pylint特性的一个完整列表。
1.1.3. 如何由python脚本创建一个单独的二进制文件?
如果你只是希望用户运行一个单独的程序而不需要预先下载一个python的发行版,则并不需要将Python代码编译成C代码。有很多工具可以找出程序依赖的模块并将这些模块 与程序绑定在一起以产生一个单独的执行文件。
其中一种工具就是freeze tool, 它作为Tools/freeze被包含在python的代码树中。它将python字节码转换成C数组,和一个可将你所有模块嵌入到新程序中的编译器,这个编译器跟python模块链接在一起。
它根据import语句递归地扫描源代码,并查找在标准python路径中的模块和源代码目录中的模块(内建模块)。用python写的模块的字节码随后被转换成C代码(可以通过使用marshal模块转换成代码对象的数组构 造器),并产生一个可自定义的配置文件,只包含程序使用了的模块。 最后将生成的C代码编译并链接至余下的的python解释器,产生一个与你的script执行效果完全一样的单独文件。
显然,freeze需要一个C编译器。但也有一些工具并不需要。首先便是Gordon McMillan's installer,它在
它工作在Windows, Linux和至少是部分Unix变种上。
另一个便是Thomas Heller的 py2exe (只适用于Windows平台),它在
第三个是Christian Tismer的 SQFREEZE,它将字节码附在一个特殊的python解释器后面,解释器负责找到这段代码。Python 2.4可能会引入类似的机制。
其它工具包括Fredrik Lundh的 Squeeze 和 Anthony Tuininga的 cx_Freeze.
1.1.4. 是否有关于python程序的代码标准或风格向导?
是的。标准库模块要求的代码风格被列在PEP 8.
1.1.5. 程序执行速度太慢,如何改善?
一般来说这是个复杂的问题。有很多技巧可以提升python的速度,比如可以用C重写部分代码。
在某些情况下将python转换成C或x86汇编语言是可能的,这意味着您不需要修改代码就可获得速度提升。
Pyrex 可以将稍许改动过的python码转换成C扩展,并可以在很多平台上使用。
Psyco 是一个即时编译器,可将python码转换成x86汇编语言。如果你可以使用它, Psyco 可使关键函数有明显的性能提升。
剩下的问题就是讨论各种可稍许提升python代码速度的技巧。在profile指出某个函数是一个经常执行的热点后,除非确实需要,否则不要应用任何优化措施,优化经常会使代码变得不清晰,您不应该承受这样做所带来的负担(延长的开发时间,更多可能的bug),除非优化结果确实值得你这样做。
Skip Montanaro有一个专门关于提升python代码速度的网页,位于 http://manatee.mojam.com/~skip/python/fastpython.html。
Guido van Rossum 写了关于提升python代码速度的内容,在http://www.python.org/doc/essays/list2str.html。
还有件需要注意的事,那就是函数特别是方法的调用代价相当大;如果你设计了一个有很多小型函数的纯面向对象的接口,而这些函数所做的不过是对实例变量获取或赋值,又或是调用另一个方法,那么你应该考虑使用更直接的方式比如直接存取实例变量。也可参照profile模块(在Library Reference manual中描述),它 能找出程序哪些部分耗费多数时间(如果你有耐性的话--profile本身会使程序数量级地变慢)。
记住很多从其它语言中学到的标准优化方法也可用于python编程。比如,在执行输出时通过使用更大块的写入来减少系统调用会加快程序速度。因此CGI脚本一次性的写入所有输出就会比写入很多次小块输出快得多。
同样的,在适当的情况下使用python的核心特性。比如,通过使用高度优化的C实现,slicing允许程序在解释器主循环的一个滴答中,切割list和其它sequence对象。因此 ,为取得同样效果,为取得以下代码的效果
1 2 L2 = [] 3 for i in range[3]: 4 L2.append(L1[i])
使用
1 2 L2 = list(L1[:3]) # "list" is redundant if L1 is a list.
则更短且快得多。
注意,内建函数如map(), zip(), 和friends在执行一个单独循环的任务时,可被作为一个方便的加速器。比如将两个list配成一对:
1 2 >>> zip([1,2,3], [4,5,6]) 3 [(1, 4), (2, 5), (3, 6)]
或在执行一系列正弦值时:
1 2 >>> map(math.sin, (1,2,3,4)) 3 [0.841470984808, 0.909297426826, 0.14112000806, -0.756802495308]
在这些情况下,操作速度会很快。
其它的例子包括string对象的join()和split()方法。例如,如果s1..s7 是大字符串(10K+)那么join([s1,s2,s3,s4,s5,s6,s7])就会比s1+s2+s3+s4+s5+s6+s7快得多, 因为后者会计算很多次子表达式,而join()则在一次过程中完成所有的复制。对于字符串操作,对字符串对象使用replace()方法。仅当在没有固定字符串模式时才使用正则表达式。考虑使用字符串格式化操作string % tuple和string % dictionary。
使用内建方法list.sort()来排序,参考sorting mini-HOWTO中关于较高级的使用例子。除非在极特殊的情况下,list.sort()比其它任何 方式都要好。
另一个技巧就是"将循环放入函数或方法中" 。例如,假设你有个运行的很慢的程序,而且你使用profiler确定函数ff()占用了很多时间。如果你注意到ff():
def ff(x):
- ..do something with x computing result... return result
常常是在循环中被调用,如:
1 2 list = map(ff, oldlist)
或:
1 2 for x in sequence: 3 value = ff(x) 4 ...do something with value...
那么你可以通过重写ff()来消除函数的调用开销:
1 2 def ffseq(seq): 3 resultseq = [] 4 for x in seq: 5 ...do something with x computing result... 6 resultseq.append(result) 7 return resultseq
并重写以上两个例子:
list = ffseq(oldlist)
和
1 2 for value in ffseq(sequence): 3 ...do something with value...
单独对ff(x)的调用被翻译成ffseq([x])[0],几乎没有额外开销。当然这个技术并不总是合适的,还是其它的方法。
你可以通过将函数或方法的定位结果精确地存储至一个本地变量来获得一些性能提升。一个循环如:
1 2 for key in token: 3 dict[key] = dict.get(key, 0) + 1
每次循环都要定位dict.get。如果这个方法一直不变,可这样实现以获取小小的性能提升:
1 2 dict_get = dict.get # look up the method once 3 for key in token: 4 dict[key] = dict_get(key, 0) + 1
默认参数可在编译期被一次赋值,而不是在运行期。这只适用于函数或对象在程序执行期间不被改变的情况,比如替换
1 2 def degree_sin(deg): 3 return math.sin(deg * math.pi / 180.0)
为
1 2 def degree_sin(deg, factor = math.pi/180.0, sin = math.sin): 3 return sin(deg * factor)
因为这个技巧对常量变量使用了默认参数,因而需要保证传递给用户API时不会产生混乱。
1.2. 核心语言
1.2.1. 如何在一个函数中设置一个全局变量?
你是否做过类似的事?
1 2 x = 1 # make a global 3 4 def f(): 5 print x # try to print the global 6 ... 7 for j in range(100): 8 if q>3: 9 x=4
任何函数内赋值的变量都是这个函数的local变量。除非它专门声明为global。作为函数体最后一个语句,x被赋值,因此编译器认为x为local变量。而语句print x 试图 print一个未初始化的local变量,因而会触发NameError 异常。
解决办法是在函数的开头插入一个明确的global声明。
1 2 def f(): 3 global x 4 print x # try to print the global 5 ... 6 for j in range(100): 7 if q>3: 8 x=4
在这种情况下,所有对x的引用都是模块名称空间中的x。
1.2.2. python中local和global变量的规则是什么?
在Python中, 某个变量在一个函数里只是被引用,则认为这个变量是global。如果函数体中变量在某个地方会被赋值,则认为这个变量是local。如果一个global变量在函数体中 被赋予新值,这个变量就会被认为是local,除非你明确地指明其为global。
尽管有些惊讶,我们略微思考一下就会明白。一方面,对于被赋值的变量,用关键字 global 是为了防止意想不到的边界效应。另一方面,如果对所有的global引用都需要关键字global,则会不停地使用global关键字。需要在每次引用内建函数或一个import的模块时都声明global。global声明是用来确定边界效应的,而这 种混乱的用法会抵消这个作用。
1.2.3. 如何在模块间共享global变量?
在一个单独程序中,各模块间共享信息的标准方法是创建一个特殊的模块(常被命名为config和cfg)。仅需要在你程序中每个模块里import这个config模块。 因为每个模块只有一个实例,对这个模块的任何改变将会影响所有的地方。例如:
config.py:
1 2 x = 0 # Default value of the 'x' configuration setting
mod.py:
1 2 import config 3 config.x = 1
main.py:
1 2 import config 3 import mod 4 print config.x
注意,由于同样的原因,使用模块也是实现Singleton设计模式的基础。
1.2.4. 什么是import模块的最好方式?
通常情况下,不要使用from modulename import * 这种格式。这样做会使引入者的namespace混乱。很多人甚至对于那些专门设计用于这种模式的模块都不采用这种方式。被设计成这种模式的模块包括Tkinter, 和threading.
在一个文件的开头引入模块。这样做使得你的你的代码需要哪些模块变得清晰,并且避免了模块名称是否存在的问题。 在每行只使用一次import使得添加和删除模块import更加容易,但每行多个import则减少屏幕空间的使用。
应该按照以下顺序import模块:
- 标准库模块 -- 如 sys, os, getopt 等
-
第三方模块(安装在python的site-packages目录下) -- 如 mx.DateTime, ZODB, PIL.Image, 等。
- 本地实现的模块。
不要使用相对的import。如果你在编写package.sub.m1 模块的代码并想 import package.sub.m2, 不要只是 import m2, 即使这样是合法的。用 from package.sub import m2 代替. 相对的imports会导致模块被初始化两次,并产生奇怪的bug。
有时需要将import语句移到函数或类中来防止import循环。 Gordon McMillan 说:
-
在两个模块都使用 "import <module>" 格式时是没问题的 。但若第二个模块想要获取第一个模块以外的一个名称("from module import name")且这个import语句位于最顶层时,则会产生错误 。因为这时第一个模块的名称并不处于有效状态,因为第一个模块正忙于import第二个模块。
在这种情况下,如果第二个模块只是用在一个函数中,那么可以简单地把import移入到这个函数中。当这个import被调用时,第一个模块已经完成了初始化,而第二个模块 则可以完成它的import语句了。
如果某些模块是系统相关的,那么将import移出顶层代码也是必要的。在那种情况下,甚至不可能在文件的顶层import所有的模块。在这种情况下,在对应的系统相关代码中引入这些模块则是个好的选择。
在解决诸如防止import循环或试图减少模块初始化时间等问题,且诸多模块并不需要依赖程序是如何执行的情况下,这种方法尤其有用。如果模块只是被用在某个函数中,你也可以将import移到这个函数中。注意首次import模块会花费较多的时间,但多次地import则几乎不会再花去额外的时间,而只是需要两次的字典查询操作。即使模块名称已经处在scope外,这个模块也很有可能 仍处在sys.modules中。
如果只是某个类的实例使用某个模块,则应该在类的__init__ 方法里import模块并把这个模块赋给一个实例变量以使这个模块在对象的整个生命周期内一直有效(通过这个实例变量)。注意要使import推迟到类的实例化,必须将import放入某个方法中。在类里所有方法之外的地方放置import语句,仍然会 使模块初始化的时候执行import。
1.2.5. 如何将某个函数的选项或键值参数传递到另一个函数?
在函数的参数列表中使用 * 和 ** ;它将你的位置参数作为一个tuple,将键值参数作为一个字典。当调用另一个函数时你可以通过使用 * 和 **来传递这些参数:
1 2 def f(x, *tup, **kwargs): 3 ... 4 kwargs['width']='14.3c' 5 ... 6 g(x, *tup, **kwargs)
如果考虑到比python的2.0更老的版本的特殊情况,使用'apply':
1 2 def f(x, *tup, **kwargs): 3 ... 4 kwargs['width']='14.3c' 5 ... 6 apply(g, (x,)+tup, kwargs)
1.2.6. 如何编写一个带有输出参数的函数(传引用调用)?
记住在python中参数传递是动过赋值实现的。因为赋值仅是创建一个新的对对象的引用,所以在调用者和被调用者之间没有任何的别名可以使用,因此从本质上说没有传引用调用。但你可以通过一系列的方法来实现这个效果。
-
- 对结果传递一个tuple:
<script type="text/javascript"></script>切换行号显示这通常是最清晰的方法。
1 2 def func2(a, b): 3 a = 'new-value' # a and b are local names 4 b = b + 1 # assigned to new objects 5 return a, b # return new values 6 7 x, y = 'old-value', 99 8 x, y = func2(x, y) 9 print x, y # output: new-value 100
- 对结果传递一个tuple:
-
- 通过使用global变量。这不是线程安全的,所以不推荐。
-
- 传递一个可变对象:
<script type="text/javascript"></script>切换行号显示
1 2 def func1(a): 3 a[0] = 'new-value' # 'a' references a mutable list 4 a[1] = a[1] + 1 # changes a shared object 5 6 args = ['old-value', 99] 7 func1(args) 8 print args[0], args[1] # output: new-value 100
- 传递一个可变对象:
-
- 传递一个可变字典:
<script type="text/javascript"></script>切换行号显示
1 2 def func3(args): 3 args['a'] = 'new-value' # args is a mutable dictionary 4 args['b'] = args['b'] + 1 # change it in-place 5 6 args = {'a':' old-value', 'b': 99} 7 func3(args) 8 print args['a'], args['b']
- 传递一个可变字典:
-
- 或者是将它绑定在一个类的实例中:
<script type="text/javascript"></script>切换行号显示但这样会使程序变得复杂,并不是一个好方法。
1 2 class callByRef: 3 def __init__(self, **args): 4 for (key, value) in args.items(): 5 setattr(self, key, value) 6 7 def func4(args): 8 args.a = 'new-value' # args is a mutable callByRef 9 args.b = args.b + 1 # change object in-place 10 11 args = callByRef(a='old-value', b=99) 12 func4(args) 13 print args.a, args.b
- 或者是将它绑定在一个类的实例中:
最好的方法还是返回一个包含多个结果的tuple。
1.2.7. 如何使用python中更高 阶的函数?
有两个选择:你可以使用内嵌的方式或使用可调用对象。比如,假设你想定义 linear(a,b),
它返回计算a*x+b 的函数f(x)。使用内嵌的方法:
1 2 def linear(a,b): 3 def result(x): 4 return a*x + b 5 return result
或者使用可调用的类:
1 2 class linear: 3 def __init__(self, a, b): 4 self.a, self.b = a,b 5 def __call__(self, x): 6 return self.a * x + self.b
两种方法都是:
1 2 taxes = linear(0.3,2)
给出一个可调用对象,taxes(10e6) 0.3 * 10e6 + 2。
用可调用对象的方法有个缺点,那就是这样做会慢一些且代码也会长一些。但是,注意到一系列的可调用对象可通过继承共享信号。
1 2 class exponential(linear): 3 # __init__ inherited 4 def __call__(self, x): 5 return self.a * (x ** self.b)
对象可以对若干方法封装状态信息:
1 2 class counter: 3 value = 0 4 def set(self, x): self.value = x 5 def up(self): self.value=self.value+1 6 def down(self): self.value=self.value-1 7 8 count = counter() 9 inc, dec, reset = count.up, count.down, count.set
这里inc(), dec() 和 reset() 运性起来就像是一组共享相同计数变量的函数。
1.2.8. 如何在python中复制一个对象?
通常,使用copy.copy() 或 copy.deepcopy()。并不是所有的对象都可以被复制,但大多数是可以的。
某些对象可以被简单地多的方法复制。字典有个copy() 方法:
1 2 newdict = olddict.copy()
序列可以通过slicing来复制:
1 2 new_l = l[:]
1.2.9. 如何查看某个对象的方法和属性?
对于一个用户定义的类的实例x,dir(x) 返回一个按字母排序的列表,其中包含了这个实例的属性和方法,类的属性。
1.2.10. 如何在运行时查看某个对象的
发表评论
发表评论
-
[Python Tips]去除 Trivial 赋值语句
2009-12-10 11:00 998[Python Tips]去除 Trivial 赋值语句 写 ... -
Mix-in技术介绍
2009-12-10 10:18 19691. Mix-in技术介绍 Mixin可以译为混入,就是在不改 ... -
Pythonic到底是什么玩意儿?
2009-12-10 09:02 918Pythonic到底是什么玩意儿? 作者:Martijn Fa ... -
python mysqldb 查询返回字典结构
2009-12-10 06:45 2667MySQLdb默认查询结果都是返回tuple,输出时候不是很方 ... -
Python学习笔记(实用技巧)
2009-12-09 02:55 1173一、如何实现系统的灵活扩展 在实际的应用中,经常要考虑 ... -
可爱的 Python: Decorator 简化元编程
2009-12-09 02:40 2768Python 使元编程成为可能,不过每个版本的 Python ...
相关推荐
Python编程FAQ1主要涉及到Python开发中的调试、错误检测和代码打包方面的问题。下面将详细解释这些知识点: 1. **Python调试器**: Python提供了一个名为pdb的源码级调试器,它支持设置断点、单步执行等功能。pdb...
选择合适的IDE(集成开发环境)对于提高Python编程效率至关重要。一些流行的Python IDE包括PyCharm、Visual Studio Code、Jupyter Notebook等。Stackoverflow上也有许多关于Python IDE的讨论,可以帮助开发者根据...
在这个项目中,“基于Python的自动问答系统”显然使用了Python编程语言来实现这一功能。Python因其语法简洁、库丰富以及在数据处理和自然语言处理(NLP)领域的强大支持而被广泛应用于此类任务。 【描述】:“大学...
### 编程及C/C++初学者 FAQ #### 一、引言 本文档旨在帮助初学者快速上手C/C++编程语言,并解答在学习过程中可能遇到的各种常见问题。通过集中整理与解答这些问题,帮助读者更好地理解编程的基本概念,顺利运行...
"Python_Pro编程_FAQ.pdf"可能是一本面向进阶用户的Python编程常见问题解答集,其中可能包含了关于高级Python特性的问题,如生成器、装饰器、上下文管理器、元类,以及优化和调试技巧。 "Python_02(较高级).pdf...
### 使用WxPython进行Win32下的Python编程深入解析 #### 一、获取WxPython资源 对于希望在Win32环境下使用WxPython进行Python编程的开发者来说,获取资源是一个重要的步骤。根据文档中的信息,我们可以从以下途径...
Python3.8官方中文API参考手册是一套全面的文档集合,涵盖了Python编程语言的各个方面,为开发者提供了详尽的指导和参考资料。这个压缩包包含了26个PDF文档,旨在帮助用户深入理解和应用Python3.8的特性。以下是这些...
5. **Python 常见问题(FAQ)**:这里汇集了 Python 开发过程中可能会遇到的问题及其解答,包括编程陷阱、性能优化、错误调试等常见问题,是解决实际问题的好帮手。 6. **Python 3.8 有什么新变化**:这部分内容...
- **Python_Pro编程_FAQ**:汇集了常见的Python编程问题及其解答,是解决实际编程难题的实用手册。 - **Python二次开发程序详解**:专注于Python在特定领域(如游戏开发、自动化测试等)的应用实践,通过具体案例...
总之,廖雪峰的Python 3教程是一套系统全面的Python学习资源,适合零基础的编程新手,内容覆盖了从基础语法到实战开发的各个方面,通过大量的代码示例和实战练习,帮助读者快速掌握Python编程技能,并能够应用到实际...
学习Python的资源非常丰富,如IDLE内置的Python文档,提供教程、语言参考、标准库和FAQ等。此外,Python社区的网站,如Python官方论坛和灵蛇网Python论坛,为用户提供问题解答、案例分享和学习资料。在图书方面,...
在提供的文件信息中,我们可以看到有关Python编程语言以及其特定模块python-ev3dev的详细知识点。python-ev3dev是一个用于控制基于ev3dev系统的设备的Python 3库,包括控制乐高Mindstorms EV3等设备的电机、传感器、...
这份文档是初学者入门Python编程的绝佳起点。它详细介绍了Python的基本语法,包括变量、数据类型(如整型、浮点型、字符串、列表、元组、字典)、流程控制(如条件语句和循环)、函数定义与调用,以及面向对象编程的...
Python3基础教程主要涵盖了一系列...整本教程立足于Python3,意味着学习者将掌握最现代的Python编程技能。教程的结构清晰,内容全面,不仅适合编程零基础的初学者,也适合那些希望巩固基础知识和提高实践能力的程序员。
Python 3.7.0是Python编程语言的一个重要版本,带来了许多增强和改进。这个完整版的文档压缩包是学习和参考Python 3.7.0语法、特性以及标准库的宝贵资源。以下是对其中主要知识点的详细阐述: 1. **Python 3.7的新...
廖雪峰老师的Python3教程涵盖了Python编程语言的基础知识和高级特性,贯穿了从入门到进阶的所有重要概念,为编程学习者提供了全面的指导。教程从Python的基础知识开始,包括安装、解释器、基础语法和数据类型,然后...
Python 3.7.2 是一个重要的Python编程语言的稳定版本,它包含了多个改进和新特性,使得这个版本成为开发者们的首选。官方文档是学习和理解任何编程语言的基础,特别是对于初学者和专业人士来说,它提供了详尽的指南...
目录 第1章 Python 处理 cassandra 升级后的回滚脚本 第 2 章 多套方案来提高 python web 框架的并发处理能力 第 3 章 python 写报警程序中的声音实现 winsound...第 31 章 Python FAQ3-python 中 的原始(raw)字符串