builltins是python的内建模块,所谓内建模块就是python解释器运行的时候会自动导入的模块,并且我们在用模块中函数的时候默认可以不用通过模块名调用。
下面是我学习builltins模块的笔记,一些相对简单的内容就不写了。
函数部分
breakpoint()
def breakpoint(*args, **kws): # real signature unknown; restored from __doc__
"""
breakpoint(*args, **kws)
Call sys.breakpointhook(*args, **kws). sys.breakpointhook() must accept
whatever arguments are passed.
By default, this drops you into the pdb debugger.
"""
pass
我们先看下官方的解释,调用该函数的时候其实是调用了sys模块的breakpointhook()并将参数传递传入,也就是说实际起作用的是sys.breakpointhook()。
那sys.breakpointhook()做了什么呢?钩子函数首先会去访问环境变量PYTHONBREAKPOINT,然后根据其不同值确定实际的引用对象。
PYTHONBREAKPOINT可以有一下几种状态:
1、没有设置该环境变量:此时breakpointhook()会调用pdb.set_trace(),进入pdb调试器中。即此时下面的两种情况完全等价。
def add(a,b):
breakpoint()
print(a+b)
def add(a,b):
import pdb
pdb.set_trace()
print(a+b)
2、PYTHONBREAKPOINT 为空字符串,此时和没有设置环境变量的效果一样。
3、PYTHONBREAKPOINT =0,此时breakpointhook()返回NONE,不进入调试器。
4、PYTHONBREAKPOINT 为一个可调用对象,如果是内置的可调用对象,可以直接设置为PYTHONBREAKPOINT =callable,否则要设置为PYTHONBREAKPOINT = module.callable。此时breakpointhook()会调用这个对象,即breakpoint() 等价于 callable()。
虽然breakpoint是用c写的,看不到源码,但是这篇breakpoint博文用python表示了其中的逻辑,有兴趣可以看下。
compile()
def compile(*args, **kwargs): # real signature unknown
"""
Compile source into a code object that can be executed by exec() or eval().
The source code may represent a Python module, statement or expression.
The filename will be used for run-time error messages.
The mode must be 'exec' to compile a module, 'single' to compile a single (interactive) statement, or 'eval' to compile an expression.
The flags argument, if present, controls which future statements influence the compilation of the code.
The dont_inherit argument, if true, stops the compilation inheriting the effects of any future statements in effect in the code calling compile; if absent or false these statements do influence the compilation,in addition to any features explicitly specified.
"""
pass
compile可以将传入的source编译为一个可以通过exec或者eval执行的对象,也就是说compile一般就要和exec或者eval一起使用。
compile平常几乎很少用到,可以看下下面关于其用处的详细介绍。
Python built-in function “compile”. What is it used for?
compile有五个参数,source、filename、mode、flags、dont_inherit,具体介绍如下(转载):(我只是看了下前三个参数。。)
1、source是一串字符串的源码,或者是AST对象数组。
2、filename是读取字符串的文件对象,如果不是从文件里读取源码来编译,那么这里可以放一些用来标识这些代码的字符串。
3、mode是用来指明那种表示的源码类型;如果是exec类型,表示这是一个序列语句,可以进行运行;如果是eval类型,表示这是一个单一的表达式语句,可以用来计算相应的值出来;如果是single类型,表示这是一个单一语句,采用交互模式执行,在这种情况下,如果是一个表达式,一般会输出结果,而不是打印为None输出。
4、可选参数flags和dont_inherit是用来控制编译源码时的标志,可以查看PEP236文档来了解这些参数,以及相关编译的说明。如果两者使用缺省参数(也即两者都是零值),在调用本函数编译时,主要使用代码中指明的编译特征来对待;如果flags参数设置有值,而dont_inherit没有设置(即是零值),那么编译代码时,不仅源码的编译特征起作用,而且flags指明的特征也起作用,相当两者的并集;如果参数dont_inherit设置有值(即是非零值),编译语句时只有参数flags指明的编译特征值起作用,即是不使用源码里指明的特征。
eval 和exec
def eval(*args, **kwargs): # real signature unknown
"""
Evaluate the given source in the context of globals and locals.
The source may be a string representing a Python expression
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
"""
pass
def exec(*args, **kwargs): # real signature unknown
"""
Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
"""
pass
我们看eval和exce的解释很类似。首先都是一个source参数,可以是代表python代码的字符串或者是compile函数返回的对象。其次都可以传入可选的globals和locals参数,globals必须是字典,locals可以是任意的映射对象。
在执行过程中,eval和exce会执行source中的代码,并将locals和globals作为局部命名空间和全局命名空间区查找相应的变量,如果没有传入globals和locals的话,就在当前的局部命名空间和全局命名空间中查找相应的变量。
我们知道,python查找变量时,顺序为局部命名空——全局命名空间——内置命名空间,也就是说在执行代码的时候,优先用locals中的变量,locals中没有,再去globals中找。
下面以eval举几个栗子。
首先不传globals和locals参数
a = 5
b = 7
def f1():
a = 3
b = 7
print(eval('a+b'))
def f2():
print(eval('a+b'))
f1()
f2()
执行结果为:10 12
上面的代码中我们并没有传入globals和locals参数,所以查找变量默认是在eval执行的局部命名空间和全局命名空间中查找。对f1来说,当前的局部命名空间中定义了a、b,所以执行3+7;对f2来说,当前的局部命名空间中没有定义a、b,全局命名空间中定义了a、b,所以执行了5+7。
a = 5
b = 7
def f1():
a = 3
b = 7
print(eval('a+b',{'a':4,'b':5},{'b':7}))
def f2():
print(eval('a+b',{'a':3}))
f1()
f2()
执行结果为:11 NameError: name ‘b’ is not defined
当传入globals和locals参数,对f1来说,首先在locals中找到b,然后去globas中找到a,执行4+7;对f2来说,在局部和全局命名空间中都找不到b,所以报错。
那么eval和exec有什么区别呢?
1、eval的source是单行的表达式;exce是多行的代码;
2、eval会有返回值,就是表达式的值;exce没有返回值;
globals和locals
def globals(*args, **kwargs): # real signature unknown
"""
Return the dictionary containing the current scope's global variables.
NOTE: Updates to this dictionary *will* affect name lookups in the current
global scope and vice-versa.
"""
pass
def locals(*args, **kwargs): # real signature unknown
"""
Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.
"""
pass
分别返回包含当前作用域全局变量和局部变量的字典。需要注意的是,globals返回的字典可以修改,修改后相应的变量也发生变化;locals返回的字典不能修改。
vars
def vars(p_object=None): # real signature unknown; restored from __doc__
"""
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
"""
return {}
repr
def repr(obj): # real signature unknown; restored from __doc__
"""
Return the canonical string representation of the object.
For many object types, including most builtins, eval(repr(obj)) == obj.
"""
pass
iter
def iter(source, sentinel=None): # known special case of iter
"""
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
"""
pass