python源码阅读笔记之几个值得注意的点

在扯函数的运行机制之前,先看看python虚拟机的运行。
py文件会先编译成pyc文件,生成字节码(ceval.c),再执行。
名字空间的概念:类,函数,module都有自己独有的名字空间,python在查找变量值时,会查找的是名字空间里的变量值。
在动态语言里,名字是能够找到其对应东西的唯一途径。
在python里,赋值语句的概念是创建一个对象obj,将这个对象赋值给一个名字,是不是很熟悉。
对的,这也就是为啥python会单独对字符串的dict对象做优化了。
一个对象的名字空间中的所有名字都称为对象的属性,这还牵扯到属性引用。在一个module内部都维护着自己的作用域。
与动态不符的一点是,一个约束是否其作用取决于源程序的文本,也就是说文本的位置决定着这个约束是否起作用。
作用域嵌套:由一个赋值语句引进的名字在这个赋值语句所在的作用域是可见的,而且在其嵌套的每个作用域也可见,
除非它被嵌套于内部,引进同样名字的另一条赋值语句所遮蔽。
python查找变量也是这么查找的LGB,module的作用域-global,函数的是-local,最顶层的作用域-builtin。

再简单聊聊python的一般表达式和条件语句:
1.在python中数值运算不是简单的数值运算,会牵扯到很多对象的检查。如下所示:
            w = POP();
            v = TOP();
            if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
                /* INLINE: int + int */
                register long a, b, i;
                a = PyInt_AS_LONG(v);
                b = PyInt_AS_LONG(w);
                /* cast to avoid undefined behaviour
                   on overflow */
                i = (long)((unsigned long)a + b);
                if ((i^a) < 0 && (i^b) < 0)
                    goto slow_add;
                x = PyInt_FromLong(i);
            }
            else if (PyString_CheckExact(v) &&
                     PyString_CheckExact(w)) {
                x = string_concatenate(v, w, f, next_instr);
                /* string_concatenate consumed the ref to v */
                goto skip_decref_vx;
            }
            else {
              slow_add:
                x = PyNumber_Add(v, w);
            }
            Py_DECREF(v);
          skip_decref_vx:
            Py_DECREF(w);
            SET_TOP(x);
            if (x != NULL) continue;
            break;
 
不简单吧
2.if中的比较操作:
            w = POP();
            v = TOP();
            if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
                /* INLINE: cmp(int, int) */
                register long a, b;
                register int res;
                a = PyInt_AS_LONG(v);
                b = PyInt_AS_LONG(w);
                switch (oparg) {
                case PyCmp_LT: res = a <  b; break;
                case PyCmp_LE: res = a <= b; break;
                case PyCmp_EQ: res = a == b; break;
                case PyCmp_NE: res = a != b; break;
                case PyCmp_GT: res = a >  b; break;
                case PyCmp_GE: res = a >= b; break;
                case PyCmp_IS: res = v == w; break;
                case PyCmp_IS_NOT: res = v != w; break;
                default: goto slow_compare;
                }
                x = res ? Py_True : Py_False;
                Py_INCREF(x);
            }
            else {
              slow_compare:
                x = cmp_outcome(oparg, v, w);
            }
            Py_DECREF(v);
            Py_DECREF(w);
            SET_TOP(x);
            if (x == NULL) break;
            PREDICT(POP_JUMP_IF_FALSE);
            PREDICT(POP_JUMP_IF_TRUE);
            continue;
在牵扯到int时,比较的很快,但是其他操作,让我们看看cmp_outcome
static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
    int res = 0;
    switch (op) {
    case PyCmp_IS:
        res = (v == w);
        break;
    case PyCmp_IS_NOT:
        res = (v != w);
        break;
    case PyCmp_IN:
        res = PySequence_Contains(w, v);
        if (res < 0)
            return NULL;
        break;
    case PyCmp_NOT_IN:
        res = PySequence_Contains(w, v);
        if (res < 0)
            return NULL;
        res = !res;
        break;
    case PyCmp_EXC_MATCH:
        if (PyTuple_Check(w)) {
            Py_ssize_t i, length;
            length = PyTuple_Size(w);
            for (i = 0; i < length; i += 1) {
                PyObject *exc = PyTuple_GET_ITEM(w, i);
                if (PyString_Check(exc)) {
                    int ret_val;
                    ret_val = PyErr_WarnEx(
                        PyExc_DeprecationWarning,
                        "catching of string "
                        "exceptions is deprecated", 1);
                    if (ret_val < 0)
                        return NULL;
                }
                else if (Py_Py3kWarningFlag  &&
                         !PyTuple_Check(exc) &&
                         !Py3kExceptionClass_Check(exc))
                {
                    int ret_val;
                    ret_val = PyErr_WarnEx(
                        PyExc_DeprecationWarning,
                        CANNOT_CATCH_MSG, 1);
                    if (ret_val < 0)
                        return NULL;
                }
            }
        }
        else {
            if (PyString_Check(w)) {
                int ret_val;
                ret_val = PyErr_WarnEx(
                                PyExc_DeprecationWarning,
                                "catching of string "
                                "exceptions is deprecated", 1);
                if (ret_val < 0)
                    return NULL;
            }
            else if (Py_Py3kWarningFlag  &&
                     !PyTuple_Check(w) &&
                     !Py3kExceptionClass_Check(w))
            {
                int ret_val;
                ret_val = PyErr_WarnEx(
                    PyExc_DeprecationWarning,
                    CANNOT_CATCH_MSG, 1);
                if (ret_val < 0)
                    return NULL;
            }
        }
        res = PyErr_GivenExceptionMatches(v, w);
        break;
    default:
        return PyObject_RichCompare(v, w, op);
    }
    v = res ? Py_True : Py_False;
    Py_INCREF(v);
    return v;
}

是不是感觉很复杂,一步步检查,比如tuple,list等集合操作都包括在里面了。
字节码的概念:在python2.7的opcode.h的文件中存储着一百多条字节码,可通过dis包查看


原文发布于微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文发表时间:2017-07-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA高级架构

图解Java 垃圾回收机制

  Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是...

1332
来自专栏Golang语言社区

Golang中time包用法--转

time包中包括两类时间:时间点(某一时刻)和时常(某一段时间) 1时间常量(时间格式化) const ( ANSIC = "Mon Jan...

1.4K8
来自专栏北京马哥教育

Python 源码阅读:list

源码位置 Include/listobject.h | Objects/listobject.c

1030
来自专栏码匠的流水账

聊聊hibernate的hbm2ddl的实现

hibernate-core-5.0.12.Final-sources.jar!/org/hibernate/tool/schema/spi/SchemaMan...

913
来自专栏向治洪

java垃圾回收机制,以及常用的回收算法

记得之前去平安面试的时候,面试官问到了垃圾回收,我当时也就是说说了垃圾回收的原理,但是具体有哪些实现策略,我当时是懵的。 概念: Java的垃圾回收机制是Jav...

2247
来自专栏菩提树下的杨过

mybatis的物理分页:mybatis-paginator

文件分割与合并是一个常见需求,比如:上传大文件时,可以先分割成小块,传到服务器后,再进行合并。很多高大上的分布式文件系统(比如:google的GFS、taoba...

2219
来自专栏码匠的流水账

聊聊rocketmq的RollingFileAppender

org/apache/rocketmq/logging/inner/LoggingBuilder.java

1113
来自专栏北京马哥教育

深度详解 Python yield与实现

学Python最简单的方法是什么?推荐阅读:Python开发工程师成长魔法 Python yield与实现 yield的功能类似于return,但是不同之处在于...

58712
来自专栏LhWorld哥陪你聊算法

Hadoop源码篇---解读Mapprer源码outPut输出

上次讲完MapReduce的输入后,这次开始讲MapReduce的输出。注意MapReduce的原语很重要:

1293
来自专栏程序员的SOD蜜

左求值表达式,堆栈,调试陷阱与ORM查询语言的设计

1,表达式的求值顺序与堆栈结构 “表达式” 是程序语言一个很重要的术语,也是大家天天写的程序中很常见的东西,但是表达式的求值顺序一定是从左到右么? C/C++语...

3266

扫码关注云+社区

领取腾讯云代金券