- Python有四种可调用对象:函数(BIF、UDF、lambda)、方法、类、一些类实例, 它们的别名也是可调用的
- 内建函数(Build-in Func):用C/C++编写, 在第一(内建)名称空间里,属于
_builtin_
模块并作为__builtins__
模块导入 类型为builtin_function_or_method
- 用户定义函数(User-Defined Func):通常用Python编写, 在全局名称空间里, 可以用
func_closure
钩住在其他地方定义的属性, 类型为function
udf.func_closure
:包含了自由变量的引用的单元对象元祖 - 通过
lambda
来创建函数的对象除了没有命名之外, 享有和用户自定义函数相同的属性 - 用户自定义方法(User-Defined Method)是被定义为类的一部分函数, 方法通过对象的名字和句点属性标识进行命名, 除了UDM外还有BIM(内建方法, 内建类型的)
- BIM和BIF享有相同属性, 不同之处在于BIM的
__self__
属性指向一个Python对象, 而BIF指向None
- UDM与类对象是关联的(非绑定方法), 但是只能通过类的实例来调用(绑定方法), 但UMD的类型都是相同的(
instancemethod
)
- BIM和BIF享有相同属性, 不同之处在于BIM的
- 可以利用类的可调用性来创建实例(调用结果便是创建实例), 可以通过
__init__
方法来自定义实例化过程 - 类的
__call__
特殊方法允许程序员创建可调用的对象(实例), 默认是没有实现的, 如果将其覆盖实例就会成为可调用(调用该实例等于调用该方法)foo()
等价于foo.__call__(foo)
[实例将自动成为每次方法调用的第一个参数] - 代码对象:即一些不能调用的可执行对象代码块, 一个模块的代码对象是构成该模块的全部代码
- 每个可调用物的核心都是代码对象, 由语句、赋值、表达式和其他可调用物组成
- 函数对象仅是代码对象的包装, 方法则是给函数对象的包装
- 真正的代码对象:代码转换成的字节码(字节编译的代码)
- 可执行对象相关BIF:
检查调用性callable()、生成代码对象compile(string, file, type)、求值eval(obj)、求值exec obj
exec
和eval()
对可以执行字符串格式的Python代码(每次必须对其进行字节编译处理) compile(str, file, type)
提供了一次性字节代码预编译, 第三个参数的可能值:可求值表达式eval
、单一执行语句single
、可执行语句组exec
eval(obj, g, l)
:对表达式求值, 该值可以为字符串或内建函数compile()
创建的预编译代码对象- 二参三参:全局和局部名称空间中的对象,
globals
需字典,locals
可以是任意映射对象(如实现了__getitem__()
方法的对象) - 二三参默认为
globals()
和locals()
返回的对象 (若传入了一个全局字典, 那么该字典会作为locals
传入)
- 二参三参:全局和局部名称空间中的对象,
exec obj
:obj
只能是原始的字符串, 比如单一执行语句或可执行语句组, 除了obj
它还可以接收有效的Py
文件对象(一旦执行完毕停留在EOF
)- EOF: end-of-file 文件末尾
input()
:返回的数据是对输入表达式求值的结果, 是eval()
和raw_input()
的组合, 等价于eval(raw_input())
- 导入模块的副作用是会导致最高级代码运行
execfile(fname, g, l)
:仅可以在现有的执行环境下运行(比如自己的全局和局部的名称空间), 不保证不会修改局部名称空间 等价于f = open(fname, 'r'); exec f; f.close()
- 在命令行中不给出完全的路径名来运行模块:
python -c "需要运行的模块"
python -m mname
:能够在类库中执行作为脚本的模块而不是作为导入的模块(使得__name__ == "__main__"
)- 为外部程序执行提供的os模块: 表见P429
os.system(str)
:接收字符串形式的系统命令并执行它, 通过退出状态显示成功或失败(非0失败, 0成功)os.popen()
:建立一个指向那个程序的单项连接, 然后像访问程序一样访问这个程序,它返回一个类文件对象- 例:
f = os.popen('uname -a'); data = f.readlne(); f.close()
[data
中的内容同os.system('uname -a')
]
- 例:
fork()
:创建一个和父进程并行的子进程, 返回两次; 调用fork()
的原始进程称为父进程, 作为调用结果新创建的进程称为子进程- 子进程返回值永远是0, 父进程返回值永远是子进程的进程标识符(PID:Process ID) , 这样父进程可以监控所有子进程
- PID是唯一区分它们的标识, 通过PID在父进程和子进程返回时采取分流措施
exec*(cmd, args)
:用给定文件作为现在要执行的程序取代当前子程序的Python解释器, 有一参数列表(也可以给命令提供环境变量字典), 没有返回值 常用作参数列表:用户的名字、搜索路径、当前Shell、终端类型、本地化语言、机器类型、操作系统名字wait()
:收获孩子(听起来好奇怪, 原句:reaping a child), 即等待子进程完成(通常和fock和exec*一起使用), 也叫扫尾, 会挂起执行直至执行完毕或终止 当子进程完成执行, 还没有被收获的时候, 它进入了闲置状态, 变成了著名的僵尸进程(此时子进程仍保持系统资源)spawn*(mode, file, args[,env])
:在新进程中执行命令(不像fork()
分别调用两个函数来建进程), 类似于在线程中启动函数mode
(魔法模式)参数在其他操作系统中比fork()
快得多
subprocess
:前身是popen5
模块, 其中有Popen
类(取代os.popen
)、call()
函数(取代os.system
)- 限制执行的模块:
rexec
(允许沙盒中的执行代码修改内建对象),bastion
(过滤属性、包装类) , 目前已因漏洞而废弃 sys.exit()
:引发SystemExit
异常, 通常不会被捕捉(除非在try-except
语句中), 仅仅表示要退出Pythonsys.exitfunc()
:默认不可用, 当调用sys.exit()
并在解释器退出之前, 可以通过改写它以提供额外的功能os._exit(status)
:只适用特定平台(如Unix、Win32), 不执行任何清理便立即退出, 状态参数为必须项os.kill()
:模拟unix函数发送信号给进程, 参数是PID和想发送到进程的信号- 发送的典型信号有:SIGNT, SIGQUIT, SIGKILL
温故知新,高级复读机