python库

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='\t'):
        self.code = []
        self.tab = tab
        self.level = 0

    def end(self):
        self.code.append("")
        return compile(string.join(self.code,"\n"),"<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

 

 

 

 

 

posted @ 2013-09-05 17:31  lfsblack  阅读(1667)  评论(0编辑  收藏  举报