热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python字节码中的loadname和loadglobal有什么区别?

如何解决《python字节码中的loadname和loadglobal有什么区别?》经验,为你挑选了1个好方法。

加载名称接受其参数,并将存储名称存储的名称值推入参数指示的位置。load global的功能类似,但是字节码中似乎没有全局存储。那么有什么区别以及如何加载全局工作



1> Christian De..:

LOAD_NAME和之间的区别LOAD_GLOBAL是他们搜索给定的位置name

LOAD_NAME

当Python遇到LOAD_NAME操作码时:

首先搜索f_locals-当前框架对象本地的名称。

如果在中找不到给定名称f_locals,则继续在中搜索f_globals-框架对象的全局名称。这些是框架对象周围范围内的名称。

如果未在其中找到名称f_globals,则进行搜索f_builtinsf_builtins是Python使用的内置名称的字典。

如果以上所有方法均失败,Python将引发一个NameError

这里是虚拟机执行LOAD_NAME指令的相关C代码:

    TARGET(LOAD_NAME) {
        PyObject *name = GETITEM(names, oparg);
        PyObject *locals = f->f_locals;
        PyObject *v;
        if (locals == NULL) {
            PyErr_Format(PyExc_SystemError,
                         "no locals when loading %R", name);
            goto error;
        }
        if (PyDict_CheckExact(locals)) {
            v = PyDict_GetItem(locals, name);
            Py_XINCREF(v);
        }
        else {
            v = PyObject_GetItem(locals, name);
            if (v == NULL) {
                if (!PyErr_ExceptionMatches(PyExc_KeyError))
                    goto error;
                PyErr_Clear();
            }
        }
        if (v == NULL) {
            v = PyDict_GetItem(f->f_globals, name);
            Py_XINCREF(v);
            if (v == NULL) {
                if (PyDict_CheckExact(f->f_builtins)) {
                    v = PyDict_GetItem(f->f_builtins, name);
                    if (v == NULL) {
                        format_exc_check_arg(
                                    PyExc_NameError,
                                    NAME_ERROR_MSG, name);
                        goto error;
                    }
                    Py_INCREF(v);
                }
                else {
                    v = PyObject_GetItem(f->f_builtins, name);
                    if (v == NULL) {
                        if (PyErr_ExceptionMatches(PyExc_KeyError))
                            format_exc_check_arg(
                                        PyExc_NameError,
                                        NAME_ERROR_MSG, name);
                        goto error;
                    }
                }
            }
        }
        PUSH(v);
        DISPATCH();
    }

LOAD_GLOBAL

当Python遇到LOAD_GLOBAL操作码时:

Python首先在中搜索名称f_globals-当前框架对象引用的周围范围中的名称。

如果未在其中找到名称f_globals,则进行搜索f_builtinsf_builtins是Python使用的内置名称的字典。

如果以上所有方法均失败,Python将引发一个NameError

这里是虚拟机执行LOAD_GLOBAL指令的相关C代码:

    TARGET(LOAD_GLOBAL) {
        PyObject *name = GETITEM(names, oparg);
        PyObject *v;
        if (PyDict_CheckExact(f->f_globals)
            && PyDict_CheckExact(f->f_builtins))
        {
            v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
                                   (PyDictObject *)f->f_builtins,
                                   name);
            if (v == NULL) {
                if (!_PyErr_OCCURRED()) {
                    /* _PyDict_LoadGlobal() returns NULL without raising
                     * an exception if the key doesn't exist */
                    format_exc_check_arg(PyExc_NameError,
                                         NAME_ERROR_MSG, name);
                }
                goto error;
            }
            Py_INCREF(v);
        }
        else {
            /* Slow-path if globals or builtins is not a dict */

            /* namespace 1: globals */
            v = PyObject_GetItem(f->f_globals, name);
            if (v == NULL) {
                if (!PyErr_ExceptionMatches(PyExc_KeyError))
                    goto error;
                PyErr_Clear();

                /* namespace 2: builtins */
                v = PyObject_GetItem(f->f_builtins, name);
                if (v == NULL) {
                    if (PyErr_ExceptionMatches(PyExc_KeyError))
                        format_exc_check_arg(
                                    PyExc_NameError,
                                    NAME_ERROR_MSG, name);
                    goto error;
                }
            }
        }
        PUSH(v);
        DISPATCH();
    }

那么,有什么区别呢?

您可能会看到,不同之处在于LOAD_GLOBAL直接跳到搜索框架对象的全局名称,而LOAD_NAME开始搜索局部名称并向上搜索。LOAD_GLOBAL对于Python已经知道名称不能为本地名称的情况,该操作码很有用,因此它完全跳过搜索本地名称。

注意:如果您想了解有关Python虚拟机如何工作的更多信息,请查看Byterun,它是CPython虚拟机的纯Python实现。它还附带有Allison Kaptur的文章。


推荐阅读
author-avatar
凡秘能
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有