Python基础:27执行环境

来源:互联网 发布:软件测试面试注意事项 编辑:程序博客网 时间:2024/05/21 08:54

一:可调用对象

        可调用对象,是任何能通过函数操作符“()”来调用的对象。Python 有4种可调用对象:函数,方法,类,以及一些类的实例。

        1:函数

        python 有 3 种不同类型的函数对象。

        a:内建函数(BIFs),是用c/c++写的,编译过后放入python 解释器,然后把它们作为内建名字空间的一部分加载进系统。这些函数在_bulitin_模块中。

        内建函数属性如下表:

bif.__doc__

 文档字符串(或None)

bif.__name__

 字符串类型的文档名字

bif.__self__

 设置为None(保留给built-in 方法)

bif.__module__

 放bif 定义的模块名字(或None)

        以用dir()列出函数的所有属性:

>>> dir(type)

['__call__', '__class__', '__cmp__', '__delattr__','__doc__','__getattribute__', '__hash__', '__init__', '__module__','__name__','__new__', '__reduce__', '__reduce_ex__','__repr__', '__self__', '__setattr__','__str__']

 

        因为内建函数(BIFs)和内建方法(BIMs)属于相同的类型,所以对BIF或者BIM 调用type()的结果都是:

>>> type(dir)

<type 'builtin_function_or_method'>

        注意这不能应用于工厂函数,因为type()正好会返回产生对象的类型:

>>> type(int)

<type 'type'>

>>> type(type)

<type 'type'>

 

        b:用户定义的函数(UDF,通常是用python 写的,定义在模块的最高级,因此会作为全局名字空间的一部分装载到系统中。函数也可在其他的函数体内定义。

        用户自定义函数属性如下表:

udf.__doc__

 文档字符串(也可以用udf.func_doc)

udf.__name__

 字符串类型的函数名字(也可以用 udf.func_name)

udf.func_code

 字节编译的代码对象

udf.func_defaults

 默认的参数元组

udf.func_globals

 全局名字空间字典; 和从函数内部调用globals(x)一样

udf.func_dict

 函数属性的名字空间

udf.func_doc

 (见上面的udf.__doc__)

udf.func_name

 (见上面的udf.__name__)

udf.func_closure

 包含了自由变量的引用的单元对象元组(自用变量在UDF 中使用,但在别处定义)

 

        用户自定义的函数是“函数“类型的,如:

>>> def foo(): pass

>>> type(foo)

<type 'function'>

 

        c:通过lambda来创建函数的对象除了没有命名之外,享有和用户自定义函数相同的属性;__name__或者func_name 属性给定为字符串"<lambda>":

>>> lambdaFunc = lambda x: x * 2

>>>type(lambdaFunc)

<type 'function'>

>>> lambdaFunc.__name__

'<lambda>'

 

        一旦函数声明以后(且函数对象可用),程序员也可以自定义函数属性。所有的新属性变成udf.__dict__对象的一部分。

 

        2:方法

        a:内建方法(BIM

        内建方法的属性如下表:

bim.__doc__

 文档字串

bim.__name__

 字符串类型的函数名字

bim.__self__

 绑定的对象

 

        只有内建类型(BIT)有BIM。BIM 和BIF 两者也都享有相同属性。不同之处在于BIM 的__self__属性指向一个Python对象,而BIF 指向None:

>>> [1,2,3].append.__self__

[1,2,3]

 

        对于内建方法,type()工厂函数给出了和BIF 相同的输出:

>>>type([].append)

<type'builtin_function_or_method'>

 

        b:用户定义的方法(UDM

        UDM包含在类定义之中,无论UDM是否绑定,所有的UMD 都是相同的类型——“实例方法“如下例:

>>> class C(object):

...            def foo(self): pass

...

>>> c = C()

>>>type(C.foo)

<type'instancemethod'>

>>> type(c.foo)

 <type'instancemethod'>

 

下表展示了UDM的属性:

udm.__doc__

 文档字符串

udm.__name__

 字符串类型的方法名字(与umd.im_func.__name__相同)

udm.__module__

 定义udm 的模块的名字(或none)

udm.im_class

 方法相关联的类

udm.im_func

 方法的函数对象(见UDFs)

udm.im_self

 如果绑定的话为相关联的实例,如果非绑定位为none

 

        3:类

        “调用”类的结果便是创建了实例,即所谓的实例化。

 

        4:类的实例

        python给类提供了名为__call__的特别方法,该方法允许程序员创建可调用的对象(实例)。

        默认情况下,__call__()方法是没有实现的,这意味着大多数实例都是不可调用的。然而,如果在类定义中覆盖了这个方法,那么这个类的实例就成为可调用的了。调用这样的实例对象等同于调用__call__()方法。任何在实例调用中给出的参数都会被传入到__call()__中例子如下:

>>> class C(object):

...            def __call__(self, *args):

...                        print "I'm callable! Called with args:\n", args

...

>>> c = C()

>>> callable(c)

True

>>> c()          

I'm callable! Called with arguments:

()

>>> c(3, 'no more, no less')

I'm callable! Called with arguments:

(3, 'no more, no less')

 

二:代码对象

        每个可调用对象的核心都是代码对象,由语句,赋值,表达式,以及其他可调用对象组成。

        一般说来,代码对象可以作为函数或者方法调用的一部分来执行,也可用exec 语句或内建函数eval()来执行。

        如果要执行python代码,那么该代码必须先要转换成字节编译的代码(又称字节码)。这才是真正的代码对象。然而,它们不包含任何关于它们执行环境的信息,这便是可调用对象存在的原因,它被用来包装一个代码对象并提供额外的信息。

        函数对象仅是代码对象的包装,方法则是函数对象的包装。

 

三:可执行对象内建函数

        1:callable

        callable()是一个布尔函数,确定一个对象是否可以通过函数操作符(())来调用。如果函数可调用便返回True,否则便是False:

>>> callable(dir)           #内建函数

True

>>> callable(1)             #integer #整数

False

>>> def foo(): pass

...

>>> callable(foo)           #用户自定义函数

True

>>> callable('bar')         #字符串

False

>>> class C(object): pass

...

>>> callable(C)             #类

True

 

        2:compile

        compile()函数允许在运行时刻动态生成代码对象,然后就可以用exec语句或者内建函数eval()来执行这些对象或者对它们进行求值。

        exec 和eval()都可以执行字符串格式的Python 代码。当执行字符串形式的代码时,每次都必须对这些代码进行字节编译处理。compile()函数提供了一次性字节代码预编译,以后每次调用的时候,都不用编译了。

        compile的三个参数都是必需的,第一参数代表了要编译的python代码。第二个字符串,虽然是必需的,但通常被置为空串。该参数代表了存放代码对象的文件的名字(字符串类型)。最后的参数是个字符串,它用来表明代码对象的类型。有三个可能值:’eval’, 'single', ’exec’

        'eval'可求值的表达式[和eval()一起使用],若第一个参数是语句的话,则会返回错误,比如:

>>> astr = "print'hello ,world'"

>>> compile(astr, '','eval')

Traceback (most recent calllast):

 File "<stdin>", line 1, in <module>

 File "", line 1

    print 'hello ,world'

        ^

SyntaxError: invalid syntax

 

        'single' 单一可执行语句[和exec 一起使用],如果有多条语句的话,则只会编译第一句。

        'exec' 可执行语句组[和exec 一起使用]。例子如下:

 

>>> eval_code = compile('100 + 200', '', 'eval')

>>> eval(eval_code)

300

 

>>> single_code = compile('print "Hello world!"', '','single')

>>> single_code

<code object ? at 120998, file "", line 0>

>>> exec single_code

Hello world!

 

>>> exec_code = compile("""

... req = input('Count how many numbers? ')

... for eachNum in range(req):

... print eachNum

... """, '', 'exec')

>>> exec exec_code

Count how many numbers? 6

0

1

2

3

4

5

 

    3:eval

        eval()对表达式求值,不能处理语句。第一个参数可以为字符串或内建函数complie()创建的预编译代码对象。第二个和第三个参数,都为可选的,分别代表了全局和局部名字空间中的对象。如果给出这两个参数,globals 必须是个字典,locals可以是任意的映射对象。

        如果都没给出这两个参数,分别默认为globals()和locals()返回的对象,如果只传入了一个全局字典,那么该字典也作为locals 传入。例子如下:

>>> eval('100 + 200')

300

        在这种情况下,eval()接收一个字符串并把"100+200"作为表达式求值,当进行整数加法后,给出返回值300。

        eval()函数的工作方式:对表达式两端的引号视而不见,接着假设“如果我是python 解释器,我会怎样去观察表达式呢?”,换句话说,如果以交互方式输入相同的表达式,解释器会做出怎么样的反应呢?按下回车后的结果应该和eval()返回的结果相同。

 

        4:exec

        exec 语句执行代码对象或字符串形式的python代码。类似地,用compile()预编译重复代码有助于改善性能。

        exec语句只接受一个参数,下面便是它的通用语法:exec obj

        被执行的对象(obj)可以只是原始的字符串,比如单一语句或是语句组,它们也可以预编译成一个代码对象。例子如下:

>>> exec """

... x = 0

... print 'x is currently:', x

... while x < 5:

... x += 1

... print 'incrementing x to:', x

... """

x is currently: 0

incrementing x to: 1

incrementing x to: 2

incrementing x to: 3

incrementing x to: 4

incrementing x to: 5

 

        exec还可以接受有效的python 文件对象。如果我们用上面的多行代码创建一个叫xcount.py 的文件,那么也可以用下面的方法执行相同的代码:

>>> f = open('xcount.py')

>>> exec f

x is currently: 0

incrementing x to: 1

incrementing x to: 2

incrementing x to: 3

incrementing x to: 4

incrementing x to: 5

 

        5:input

        input()是eval()和raw_input()的组合,等价于eval(raw_input())。

        类似于raw_input(),input()有一个可选的参数,该参数代表了给用户的字符串提示。该字符串默认为空串。

        从功能上看,input 不同于raw_input(),因为raw_input()总是以字符串的形式,逐字地返回用户的输入。input()履行相同的的任务;而且,它还把输入作为python 表达式进行求值。这意味着input()返回的数据是对输入表达式求值的结果:一个python 对象。例子如下:

>>> aString = raw_input('Enter a list: ')

Enter a list: [ 123, 'xyz', 45.67 ]

>>> aString

"[ 123, 'xyz', 45.67 ]"

>>> type(aString)

<type 'str'>

 

>>> aList = input('Enter a list: ')

Enter a list: [ 123, 'xyz', 45.67 ]

>>> aList

[123, 'xyz', 45.67]

>>> type(aList)

<type 'list'>

        虽然用户输入字符串,但是input()把输入作为python 对象来求值并返回表达式的结果。

 

四:执行其他Python程序

        1:execfile()

通过exec语句来读取python脚本的内容并执行,例子如下:

f = open(filename, 'r')

exec f

f.close()

 

        这3行可以调用execfile()来换掉:execfile(filename)

        在某些情况下,可能需要用不同全局和局部的名字空间集合,而不是默认的集合来执行模块。execfile() 函数的语法非常类似于eval()函数的:

        execfile(filename, globals=globals(), locals=locals())

        类似eval(),globals 和locals 都是可选的,如果不提供参数值的话,默认为执行环境的名字空间。如果只给定globals,那么locals 默认和globals 相同。

 

        2:将模块作为脚本执行

        python2.4里加入了一个新的命令行选项-m, 允许从shell 或DOS 提示符,直接把模块作为脚本来执行。

 

        模块是标准库的一部分,安装在site-packages 里,或者仅仅是包里面的模块,那直接运行该模块脚本就不是那么容易了。比如,想运行免费的python web服务器,以便创建和测试你自己的web 页面和CGI 脚本。则必须在命令行敲入如下的东西:

$ python /usr/local/lib/python2x/CGIHTTPServer.py

Serving HTTP on 0.0.0.0 port 8000 ...


        如果它是第三方的,则不得不深入到site-packages 去找到它真正定位的地方。


        如果不给出完全的路径名,可以用python -c命令行开关,从命令行运行一个模块,并让python 的导入机制做这种跑腿工作:

$ python -c "import  CGIHTTPServer; CGIHTTPServer.test()"

        该选项允许指定想要运行的python 语句。虽然这样可以工作,但是__name__模块不是‘__main__’,而是你正在使用的模块。解释器通过import 装载了你的模块,并不是它当作脚本。因此,所有在if __name__ == '__main__' 之下的代码是不会执行的,所以不得不手动地调用模块的test()函数。

 

        要想同时要两者的优点——能够在类库中作为脚本执行模块,而不是作为导入的模块。这就是-m 参数的动机。现在可以像这样运行脚本:

$ python -m  CGIHTTPServer

 

五:执行其他非Python程序

        也可以执行非python 程序。这些程序包括了二进制可执行文件,其他的shell 脚本等等。

1:os.system

        一个非常简单的函数,接收字符串形式的系统命令并执行它。当执行命令的时候,python的运行是挂起的。当我们的执行完成之后,将会以system()的返回值形式给出退出状态,python 的执行也会继续。

        system()保留了现有的标准文件,包括标准的输出,意味着执行任何的命令和程序显示输出都会传到标准输出上。

        system()通常和不会产生输出的命令一起使用,通过退出状态显示成功或失败,0 表示成功,非零表示其他类型的错误。例子如下:

>>> import os

>>> result = os.system('cat /etc/motd') Have a lot of fun...

>>> result

0

>>> result = os.system('uname -a')

Linux solo 2.2.13 #1 Mon Nov 8 15:08:22 CET 1999 i586 unknown

>>> result

0

 

六:结束执行

        1:sys.exit() 和 SystemExit

        立即退出程序并返回调用程序的主要方式是sys模块中的exit()函数。语法为:

sys.exit(status=0)

        当调用sys.exit()时,就会引发systemExit()异常。除非对异常在一个try 语句和合适的except子句中进行捕获,否则解释器会用给定的状态参数退出,如果没有给出的话,该参数默认为0。

        SystemExit 是唯一不看作错误的异常。它仅仅表示要退出python。

        2:os.kill

        os模块的kill()函数模拟传统的unix函数来发送信号给进程。kill()参数是进程标识数(PID)和你想要发送到进程的信号。发送的典型信号为SIGINT、SIGQUIT或SIGKILL,来使进程终结。

0 0
原创粉丝点击