zoukankan      html  css  js  c++  java
  • python种的builtin函数详解第三篇 C

    exec_stmt ::= "exec" or_expr ["in" expression ["," expression]]
    eval(expression[, globals[, locals]])
    execfile(filename[, globals[, locals]])
    Help on built-in function execfile in module __builtin__:
    execfile(...)
    execfile(filename[, globals[, locals]])
    Read and execute a Python script from a file.
    The globals and locals are dictionaries, defaulting to the current
    

    这几个函数都非常类似,第一个 [exec] () 在python2 中还是一个语句,在python3中 execprint 都被实现成为了 buildin 函数。

    这3个 “函数” 的作用都是去执行一段 python 代码字符串, 和js中的eval有类似的作用,其中 exec 表达式的参数 可以是一个code对象,一个打开的文件,一个unicode字符串,其中code对象可以通过 compile 这个内置函数生成。

    eval 函数的参数只能是一个表达式,不能是语句,如果没有仔细看文档的话,非常有可能写出如下的代码:

    eval(" print 'test' ")
    

    这个时候你就会得到一个无情的 SyntaxError , 而 execexecfile 即可以执行语句,也可以执行表达式。

    execfile的第一个参数是一个文件名字符串,它会把相应的文件载入内存,然后像 exec 语句一样执行, 所以这里我拿exec来做例子, 其余的2个参数都是关于执行的语句与表达式的环境变量,loclas是本地变量作用域,globals是全局作用域, 需要说明的是,当没有提供2个参数的时候,代码块执行的上下文就是语句和表达式执行的上下文,如果只提供了globals,那么, locals就是globals,关于为什么globals在locals前面的问题,就非常显而易见了,见下面的代码:

    >>> exec "print test(name)" in {'test': lambda name:name, 'name' : 'younger'}, {'test': lambda name:name, 'name' : 'test'}
    
    test
    
    >>>exec "print test(name)" in {'test': lambda name:name, 'name' : 'younger'}
    younger
    

    我在第一次研究这3个方法的时候,陷入了一个误区,这个误区就是关于变量作用域的,见如下的代码:

    def test(name):
    	print name
    
    >>> exec "test(name)" in {'name' : 'name'}
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<string>", line 1, in <module>
    NameError: name 'test' is not defined
    

    是的,我在外部作用域定义了一个方法,当我在exec中执行这个方法的时候,由于需要一个参数,所以在globals里面写了name属性, 结果test自然就找不到了,一开始一直以为只有变量才会在globals中和locals中去寻找,忘记了函数也是第一类值,所以上面的写法是完全错误的.

    其次还有 __builtins__ 这个字典会被自动注入到exec 的globals里面,前提是在语句中提供globals, 可以是空的,也可以是带参数的。

    exec "print globals()" in {'s':'s'}
    exec "print locals()" in {}
    

    上面的2个语句执行结果完全一样.

    关于globals和locals的副作用,在执行的语句是付值语句或者是会对变量产生影响的语句的时候,就会影响到你的locals和globals变量,当你期望从globals或者locals中得到有用信息的时候,就要小心这个副作用了

    a = {'a' : 1}
    b = {}
    exec "a = a + 1" in a, b
    print a['a']
    print b['b']
    
    >>> 1
    >>>2
    

    结果显而易见,如果你执行 print a ,的话,内置的builtin会全部输出,包括copyright信息在内。

    关于那些显而易见的好用方法,暂时没有挖掘出有价值的使用技巧,所以就不多加叙述了,既然显而易见,那么肯定很好用就对了.

    所以从现在开始,尽量去说一些带坑的方法,包括使用技巧和部分原理性的东西,希望能把自己的知识点梳理完整.

  • 相关阅读:
    敏捷开发方法综述
    RBAC权限控制系统
    Thinkphp 视图模型
    Thinkphp 缓存和静态缓存局部缓存设置
    Thinkphp路由使用
    Thinkphp自定义标签
    异步处理那些事
    Thinkphp 关联模型
    Thinkphp 3.1. 3 ueditor 1.4.3 添加水印
    数据库组合
  • 原文地址:https://www.cnblogs.com/youngershen/p/3996998.html
Copyright © 2011-2022 走看看