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