Python核心编程--执行环境

来源:互联网 发布:js 替换某个标签 编辑:程序博客网 时间:2024/06/05 05:07

执行环境

1. 可调用对象

可调用,即可以通过函数操作符“()”来调用的对象,包括函数、方法、类、实例。

1.1 函数

Python有三类函数, 即内置函数(Build-in Function, BIF)和用户定义函数(User Defined Function, UDF) 和 lambda表达式。

内置函数 BIF

定义在模块__bulitin__中的函数,整个__bulitin__会被默认地载入Python 解释器,print locals(), 会看到:

{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}

print __bulitins__.__dict__就可以看到内置函数列表(其实不止内置函数)。

假如bif为一个内置函数,那么可以通过bif.__doc__查看函数的文档——其实函数就是Python中一种特殊的类型,也是有它自己的一系列属性的。

用户定义函数 UDF

用户定义在模块最外层(最顶级)的函数。

lambda表达式

用lamdba表达式生成的匿名函数。

使用方法如:

# 方法 1,即匿名函数直接作为参数传入。sortedDictItems = sorted(d.items(), key = lamdba x:x[1], reverse=True)# 方法 2,将匿名函数赋予一个引用,然后通过函数引用调用。lambdaFunc = lambda x: x * 2lambdaFunc(2)   /*结果 4*/print lambdaFunc.__doc__   /*结果 <lambda>*/

1.2 方法

方法实际上就是定义在类内部的函数。 也可以分为内置方法(BIM)和用户自定义方法(UDM).

1.3 类

假设类名为A,则 a = A()会生成类的一个实例,也就是说,类的调用实际上就是实例化的过程。

1.4 实例

一般情况下,实例是不能(通过函数操作符“()”)调用的,但如果类实现了__call__方法的话,那么该类的实例就能通过函数操作符()调用了,其行为即__call__函数的行为。

class A(object):     def __call__(self, *args):         print 'now instance is callable, args:', argsa = A()a(self, 1, 'parameter 2')/*结果:now instance is callable, args: (1, 'parameter 2')*/ 

2. 代码对象

  • 代码对象的定义:Python代码编译而成的字节码(Python代码执行都需要先转化成字节码).
  • 代码对象的执行:可以作为函数或者方法的一部分来执行,也可以用内建函数exec或者eval来执行。
  • 代码对象与函数、方法:在用户自定义函数UDF中,有一个属性udf.func_code, 即函数的字节码,而在用户自定义方法UDM中,有一个属性udm.im_func即方法对应的函数,而udm.im_func.func_code就是其字节码,也就是说,代码对象、函数、方法之间构成了这样的一种关系——函数对象是对代码对象的包装,方法则是对函数的包装。

3. 代码的编译与执行

介绍几个用于编译和执行代码(字节码代码对象或者字符串代码)的函数。

3.1 callable

callable(obj)判断obj是否可调用。

3.2 compile

输入字符串代码,生成代码对象,用于eval或者exec中执行,而不必在eval或者exec中每次都重新去编译一次。

compile有三个参数:

compile(code, filename, type)

即字符串代码,保存代码对象的文件名(通常我们并不保存为文件,因此置为空串),代码对象类型,类型有三种:

  • 'eval': 用于eval函数的可求值的表达式
  • 'single': 用于exec的单一可执行语句
  • 'exec': 用于exec的可执行语句组

如:

eval_code = compile('100 + 200', '', 'eval')eval(eval_code) /*结果:300*/single_code = compile('print "hi"', '', 'single')exec(single_code) /*结果:hi*/

3.3 eval

对表达式进行求值,当然其中还包括将代码中的变量转化为合适的类型,因此:eval('[1,2,3]')会返回一个list类型的[1,2,3].

eval有三个参数,eval(code, globals, locals),即:

  • 代码(字符串,or 代码对象)
  • 全局空间中的对象:必须是个字段,一般不传这个参数,默认为globals()
  • 局部作用域中的对象,一般不传这个字段,默认为locals()

3.4 exec

exec可以执行的对象有三种:

  • 字符串代码
  • 代码对象(如compile编译成的代码对象)
  • 文件对象(如python代码文件),执行完一遍之后,文件指针就移到了文件末尾。

    f = open('code.py')exec fprint f.tell(), os.path.getsize('code.py') /*两者相等*/f.seek(0)  /*重新移回文件头*/exec f   /*又可以执行了*/

一种应用的场景是可以根据用户的输入,在运行时来生成并执行不同的代码,不过问题是,这不也能通过函数和函数参数来实现吗,有不能用函数而需要动态生成代码的场景吗?

3.5 input

相当于eval(raw_input()), raw_input得到字符串形式的用户输入,eval再将它转化为合适的类型返回。

str_input = raw_input('please enter a list:')//输入[1, 2, 3]后的结果是 字符串"[1,2,3]"processed = input('please enter a list')// 输入[1,2,3]后返回即是list类型的[1,2,3]

3.6 其他代码执行方式

  • import导入模块:导入时会执行模块最外层的代码(因此最外层的可执行代码中那句判断if __name__ == __main__是多么地重要!)。
  • execfile(file_name):执行代码文件,相当于:

    f = open(filename, 'r')exec ff.close()
  • 将模块最为模块执行, 即python code.py para1 para2

4. 执行非Python程序

主要是通过os系列函数来执行其他非Python程序。

4.1 os.system(cmd)

执行cmd(shell) 命令。

会像执行cmd程序一样,将结果直接输出到stdout上,因此在特定的应用程序如CGI中可能会导致出问题--将我们并不希望输出到stdout的命令结果混入到有效的html字符串。因此,我们需要下面的命令:

4.2 os.popen(cmd)

执行cmd,并将结果以一个类(似)文件对象的形式返回(而不是直接输出到stdout中)。如:

import osf = os.popen('uname -a')result = f.readline()f.close()print result

4.3 os.fork()

创建一个子进程,常见的模式为:

ret = os.fork()if ret == 0:   child_codeelse:   parent_code

child_code中通常会用到os.exec*系列函数,来在子程序中装载入新的程序并设置其参数,根据不同的参数类型需要选择os.exec*系列的不同函数(详细列表见《Python核心编程 第二版》 P429)。

parent_code中则可能会用到os.wait*系列,用于等待子程序的返回或者特定的信号。

5. 终止执行

  • sys.exit() 相当于 C++中的exit(), 可以有返回值,如sys.exit(1), 会引发SystemExit异常。
  • os._exit(status): 不建议使用,只适用于特定的平台。
  • os.kill(pid, sig): 给特定pid的进程发送信号

6. 各类操作系统接口

就记几个比较有用的吧。

  • uname:获取系统信息
  • getuid/setuid: 获取/设置uid
  • getpid: 获取Pid
  • getppid: 获取父进程pid
  • getsid/setsid: 获取/设置会话ID
  • getenv(ev): 获取环境变量ev的值
  • setenv(ev, val): 设置环境变量ev的值为val
  • strerror(code): 将错误码转化为错误描述
0 0
原创粉丝点击