python中有两个模块在python启动时载入,任何程序都可以使用它们,因此它们非常重要
1,内建函数模块 __builtin__
2,异常处理相关模块 exceptions
Python有很多使用了POSIX标准API和标准C语言库的模块,它们为底层操作系统提供了平台独立的接口:
eg:
提供文件和进程处理功能的os模块
提供平台独立的文件名处理(分拆目录名,文件名,后缀等)的os.path模块
时间日期处理相关的time/datatime
其实网络和线程也可是算这一类
标准库里面还有很多用于支持内建类型操作的库
string 模块实现了字符串处理
math 提供数学计算操作和常量(pi,e)
cmath 模块为复数提供了和math一样的功能
而且python还提供了正则表达式的支持的re模块
sys模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本等
operator模块提供了和内建操作符相同的函数
copy模块允许复制对象
gc模块提供了对垃圾收集的相关控制功能
下面详细的看看这些模块的功能吧:
__builtin__模块
该模块包含了Python使用的内建函数,一般不用手动倒入这个模块
apply函数:
#builtin-apply-example-1.py def function(a,b): print a,b apply(function,("whither","canada?")) apply(function,(1,2+3))
输出:
>>> ================================ RESTART ================================
>>>
whither canada?
1 5
apply的第三个参数可以接受关键字参数:(以字典形式)
#builtin-apply-example-2.py def function(a,b): print a,b apply(function,("crunchy","frog")) apply(function,("crunchy",),{"b":"frog"}) apply(function,(),{"a":"crunchy","b":"frog"})
结果:
>>> ================================ RESTART ================================
>>>
crunchy frog
crunchy frog
crunchy frog
apply函数的一个常见用法是把构造函数参数从子类传到到基类,尤其是构造函数需要接受很多参数的时候:
#builtin-apply-example-3.py class Rectangle: def __init__(self,color="white",width=10,height=10): print "create a",color,self,"sized",width,"x",height class RoundedRectangle(Rectangle): def __init__(self,**kw): apply(Rectangle.__init__,(self,),kw) rect = Rectangle(color="green",height=100,width=100) rect = RoundedRectangle(color="blue",height=20)
结果:
>>> ================================ RESTART ================================ >>> create a green <__main__.Rectangle instance at 0x0000000002A80888> sized 100 x 100 create a blue <__main__.RoundedRectangle instance at 0x0000000002A7E088> sized 10 x 20 >>>
下面两个语句是等价的:
result = function(*args,**kwargs)
result = apply(function,args,kwargs)
加载重载模块:
我们经常用import导入其他模块,其实这个import其实是靠内建函数__import__来工作的。
功过这个方法可以动态的调用函数
当知道模块名称时候,可以很方便倒入所有以”-plugin”结尾的模块:
LOOK:
#builtin-import-example-1.py import glob,os modules = [] for module_file in glob.glob("*-plugin.py"): try: module_name,ext = os.path.splitext(os.path.basename(module_file)) module = __import__(module_name) modules.append(module) except ImportError: pass for module in modules: module.hello()
#example-plugin.py def hello(): print "example-plugin says hello"
结果:
example-plugin says hello
此处注意:plug-in模块文件名中有一个“-”.这意味着不能使用普通的import命令,因为Python的辨识符不允许有“-”
可以用__import__函数获得特定函数:
#builtin-import-example-2.py import glob,os def getfunctionbyname(module_name,function_name): module = __import__(module_name) return getattr(module,function_name) print repr(getfunctionbyname("dumbdbm","open"))
结果:
>>> ================================ RESTART ================================ >>> <function open at 0x0000000002BE0208> >>>
也可以用__import__实现延迟导入:
#builtin-import-example-3.py class LazyImport: def __init__(self,module_name): self.module_name = module_name self.module = None def __getattr__(self,name): if self.module is None: self.module = __import__(self.module_name) return getattr(self.module,name) string = LazyImport("string") print string.lowercase
结果:
>>> ================================ RESTART ================================
>>>
abcdefghijklmnopqrstuvwxyz
>>>
该例子string模块只在第一次使用的时候导入
重新加载函数reload():
#builtin-reload-example-1.py import hello reload(hello) reload(hello) reload(hello)
注意:当重新加载模块时,它会被重新编译,新的模块会代替模块字典里的老模块
但是,已经用原模块里的类建立的实例仍然使用的时老模块(不会被更新)
同样的,使用from – import直接创建的到模块内容的引用也是不会被更新的。
dir函数:
返回由给定模块,类,实例或其他类型的所有成员的列表。
可在交互式解释器下直接dir()
#builtin-dir-example-1.py def dump(value): print value,"=>",dir(value) import sys dump(0) dump(1.0) dump(0.0j) dump([]) dump({}) dump("string") dump(len) dump(sys)
#builtin-dir-example-2.py class A: def a(self): pass def b(self): pass class B(A): def c(self): pass def d(self): pass def getmembers(klass,members=None): #get a list of all class members,ordered by class if members is None: members = [] for k in klass.__bases__: getmembers(k,members) for m in dir(klass): if m not in members: members.append(m) return members print getmembers(A) print getmembers(B) print getmembers(IOError)
结果:
>>> ================================ RESTART ================================ >>> ['__doc__', '__module__', 'a', 'b'] ['__doc__', '__module__', 'a', 'b', 'c', 'd'] ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__dict__', '__getitem__', '__getslice__', '__setstate__', '__unicode__', 'args', 'message', 'errno', 'filename', 'strerror'] >>>
getmembers函数返回一个有序列表,成员在列表中名称出现的越早,它所处的类层次就越高。
字典是无序的,而列表和元组诗有序的
vars函数
返回的是包含每个成员当前值得字典。如果使用不带参数的vars,将返回当前局部名称空间的可见元素(同locals()函数)
#builtin-vars-example-1.py book = "library2" pages = 250 scripts = 350 print "the %(book)s book contaions more than %(scripts)s scripts" % vars()
结果:
>>> ================================ RESTART ================================ >>> the library2 book contaions more than 350 scripts >>>
Python是一种动态类型语言,这就是说给一个变量名可以在不同场合绑定到不同的类型上。type函数允许检查一个变量的类型,这个函数返回一个
type descriptor(类型描述符),它对于每个类型是不一样的:
#builtin-type-example-1.py def dump(value): print type(value),value dump(1) dump(1.0) dump("one")
result:
>>> ================================ RESTART ================================ >>> <type 'int'> 1 <type 'float'> 1.0 <type 'str'> one >>>
每个类型都有一个对应的类型对象,可以使用is操作符来检查类型
#builtin-type-example-2.py def load(file): if isinstance(file,type("")): file = open(file,"rb") return file.read() print len(load("builtin-vars-example-1.py")),"bytes" print len(load(open("builtin-vars-example-1.py"))),"bytes"
>>> type("") <type 'str'> >>>
result:
>>> ================================ RESTART ================================ >>> 254 bytes 245 bytes >>>
calable函数
检查一个对象是否是可调用的(无论是直接调用或是通过apply)。
对于函数,方法,lambda函式,类,以及实现了__call__方法的类实例,都返回True
#builtin-callable-example-1.py def dump(function): if callable(function): print function,"is callable" else: print function,"is *not* callable" class A: def method(self,value): return value class B(A): def __call__(self,value): return value a = A() b = B() dump(0) dump("string") dump(callable) dump(dump) dump(A) dump(B) dump(B.method) dump(a) dump(b) dump(b.method)
result:
>>> ================================ RESTART ================================ >>> 0 is *not* callable string is *not* callable <built-in function callable> is callable <function dump at 0x00000000020F0908> is callable __main__.A is callable __main__.B is callable <unbound method B.method> is callable <__main__.A instance at 0x0000000002AF01C8> is *not* callable <__main__.B instance at 0x0000000002AF0888> is callable <bound method B.method of <__main__.B instance at 0x0000000002AF0888>> is callable >>>
注意,A和B是可调用的,如果调用它们,就产生新的对象(类实例),但是A类实例不可调用,因为没有实现__call__方法
可以在operator模块中找到检查对象是否为某一内建类型(数字,序列,字典等)的函数,因为创建一个类很简单,所以对这些类型使用显式的类型判断并不是好想法
在处理类和实例的时候会复杂些,Python不会把类作为本质上的类型对待;相反的,所有类都属于一个特殊的类型,所有的类实例属于一个特殊的实例类型
>>> b = a() >>> type(a) <type 'classobj'> >>> type(b) <type 'instance'> >>> c = a() >>> type(a) <type 'classobj'> >>> type(c) <type 'instance'> >>>
所以,不能使用type函数来测试一个实例是否属于一个给定的类。
所有实例都是同样的类型!
为了解决这个问题,可以使用isinstance函数。它会检查一个对象是不是给定类(或其子类)的实例
#builtin-isinstance-example-1.py class A: pass class B: pass class C(A): pass class D(A,B): pass def dump(object): print object,"=>", if isinstance(object,A): print "A", if isinstance(object,B): print "B", if isinstance(object,C): print "C", if isinstance(object,D): print "D" print a = A() b = B() c = C() d = D() d dump(a) dump(b) dump(c) dump(d) dump(0) dump("string")
result:
>>> ================================ RESTART ================================ >>> <__main__.A instance at 0x0000000002C601C8> => A <__main__.B instance at 0x0000000002C60888> => B <__main__.C instance at 0x0000000002C60B88> => A C <__main__.D instance at 0x0000000002C60B08> => A B D 0 => string => >>>
issubclass函数和isinstance类似,它用于检查一个类对象是否与给定类相同,或者是给定类子类
注意:isinstance可以接受任何对象作为参数,而issubclass函数在接受类对象参数时会引发TypeError异常,第一个参数必须是类
#builtin-issubclass-example-1.py class A: pass class B: pass class C(A): pass class D(A,B): pass def dump(object): print object,"=>", if issubclass(object,A): print "A", if issubclass(object,B): print "B", if issubclass(object,C): print "C", if issubclass(object,D): print "D" print dump(A) dump(B) dump(C) dump(D) dump(0) dump("string")
result:
>>> ================================ RESTART ================================ >>> __main__.A => A __main__.B => B __main__.C => A C __main__.D => A B D 0 => Traceback (most recent call last): File "H:/python/strandarlib/builtin-vars-example-1.py", line 34, in <module> dump(0) File "H:/python/strandarlib/builtin-vars-example-1.py", line 18, in dump if issubclass(object,A): TypeError: issubclass() arg 1 must be a class >>>
Python提供了在程序中与解释器交互的很多方法
eval函数将一个字符串作为python表达式求值,可以传递一串文本,简单的表达式,或者使用内建python函数
#builtin-eval-example-1.py def dump(expression): result = eval(expression) print expression,"=>",result,type(result) dump("1") dump("1.0") dump("'string'") dump("1.0+2.0") dump("'*'*10") dump("len('world')")
result:
>>> ================================ RESTART ================================ >>> 1 => 1 <type 'int'> 1.0 => 1.0 <type 'float'> 'string' => string <type 'str'> 1.0+2.0 => 3.0 <type 'float'> '*'*10 => ********** <type 'str'> len('world') => 5 <type 'int'> >>>
当如这样存在风险(引入os模块,删除磁盘上文件)
#builtin-eval-example-2.py print eval("__import__('os').getcwd()") print eval("__import__('os').remove('file')")
eval第二个参数,定义了该表达式求值时命名空间字典
print eval("__import__('os').getcwd()") print eval("__import__('os').remove('file')",{"__builtins__":{}})
即使这样,仍然无法避免针对cpu和内存资源的攻击
eval(“‘*’*1000000*2*2*2*2*2*2*2*2*2”)会使程序耗尽资源
compile函数:
#builtin-compile-example-1.py NAME = "builtin-apply-example-1.py" BODY = """print 'owl-stretching time'""" try: compile(BODY,NAME,"exec") except SyntaxError,v: print "syntax error: ",v,"in",NAME
#builtin-compile-example-2.py BODY = """ print 'owl-stretching time' """ code = compile(BODY,"<script>","exec") print code exec code
可以在程序中执行实时的生成代码。
#builtin-compile-example-3.py import sys,string class CodeGeneratorBackend: "Simple code genetator for Python" def begin(self,tab=' '): self.code = [] self.tab = tab self.level = 0 def end(self): self.code.append("") return compile(string.join(self.code," "),"<code>","exec") def write(self,string): self.code.append(self.tab * self.level + string) def indent(self): self.level = self.level + 1 def dedent(self): if self.level == 0: raise SyntaxError,"internal error in code generator" self.level = self.level - 1 c = CodeGeneratorBackend() c.begin() c.write("for i in range(5):") c.indent() c.write("print 'code generation made easy!'") c.dedent() exec c.end()
result:
>>> ================================ RESTART ================================
>>>
code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!
>>>
Python还提供了execfile函数
一个从文件加载代码,编译代码,执行代码的快捷方式:
#builtin-execfile-example-1.py execfile("hello.py") def ExecFile(filename,locals=None,globals=None): exec compile(open(filename).read(),filename,"exec") in locals,globals ExecFile("hello.py")
result:
>>> ================================ RESTART ================================ >>> hello again,and welcome to the show hello again,and welcome to the show >>>
因为python在检查局部名称空间和模块名出呢个空间之前不会检查内建函数,所有有时候可能要显式引用__builtin__模块
下面例子重载了内建open函数,这时候要想使用原来的open函数,就需要脚本显式的指明模块名称:
#builtin-open-example-1.py def open(filename,mode='rb'): impot __builtin__ file = __builtin__.open(filename,mode) if file.read(5) not in ("GIF87","GIF89"): raise IOError,"not a GIF file" file.seek(0) return file fp = open("333.gif") print len(fp.read()),"bytes" print len(fp.read()),"bytes"
打开文件最好用file