如何动态修改函数的本地命名空间?

2023-12-02

注意:这个问题假设 Python 2.7.3。

我正在寻找一种合理的方法来动态修改函数的本地命名空间,最好以一种给函数体函数添加最少混乱的方式。

我的想法是这样的:

import os
from namespace_updater import update_locals

def somefunc(x, y, z):
    # ...
    # ...
    # this and that
    # ...
    # ...

    if os.environ.get('FROBNICATE'):
        from frobnitz import frobnicate
        update_locals(frobnicate(locals()))

    #
    # life goes on, possibly with duly frobnicated local variables...
    # ...
    # ...
    # ...

Thanks!


PS:以下是行不通的方法。

最幼稚的方法是这样的:

locals().update(new_locals(locals())

...但是的文档locals()非常明确地警告不要依赖此类巫毒来修改局部变量,因此请不要将其作为答案提交(除非您可以提出一个很好的案例来忽略文档的警告)。

接下来的天真的规模是这样的

for k, v in new_locals(locals()).items():
    exec ('%s = v' % k)

AFAICT,这样的代码不能“不碍事”(即,它has位于函数体内),这并不理想。但真正的破坏因素是exec ('%s = v' % k)hack 可能会导致一些奇怪的错误。

当我写“奇怪的错误”时,我的意思是“对于那些缺乏掌握的人来说看起来很奇怪的错误”exec ('%s = v' % k)正如我的”。我对这个黑客的掌握有多薄弱?要回答这个问题,请考虑下面的脚本。它有三个变体:(1) 完全如图所示;(2) 删除前导后#18号线; (3) 删除第一个后#在第 15 行和第 18 行中(即对于此变体,没有注释掉任何代码)。我无法预测该脚本的变体 (2) 和 (3) 的行为。我什至无法以超过 50% 的置信度预测变体 (1) 的行为。这就是我的把握是多么脆弱exec ('%s = v' % k)黑客。除非您能够自信且正确地预测该脚本的三个变体将如何运行(在 python 2.7 下),否则可以肯定地说,您对情况的掌握和我的一样脆弱,您可能应该远离exec ('%s = v' % k) too.

x = 'global x'                            # 01
y = 'global y'                            # 02
def main():                               # 03
    x = 'local x'                         # 04
    y = 'local y'                         # 05
    run(locals())                         # 06
    print 'OK'                            # 07
    return 0                              # 08
                                          # 09
def run(namespace):                       # 10
    global y                              # 11
    print locals().keys()                 # 12
    for k, v in namespace.items():        # 13
        print '%s <- %r' % (k, v)         # 14
        exec ('%s = v' % k) #in locals()  # 15
    print locals().keys()                 # 16
    x = x                                 # 17
    #z = lambda: k                        # 18
    print x                               # 19
    print y                               # 20
                                          # 21
exit(main())                              # 22

我将提出我能想到的唯一接近合理的方法,然后我将尝试说服您不要使用它。

def process(**kw):
  mycode = """\
print 'Value of foo is %s' % (foo,)
print 'Value of bar is %s' % (bar,)
"""
  exec mycode in kw

vars = {'foo': 2, 'bar': 3}
process(**vars)

通过这种方法,您至少可以免受代码注入攻击。包含代码“局部变量”的字典是显式指定的,因此您可以完全控制运行时的变量空间。exec陈述。您不必侵入函数对象或其他类似对象的内部。

我知道装饰器模块 uses exec在实施中@decorator在动态创建的函数中操作参数名称,并且可能有其他常见模块使用它。但我只经历过一种情况exec明显优于 Python 的替代方案,并且eval.

我在你的问题中没有看到这种情况。除非mycode从上面需要做一些非常时髦的事情,比如创建一个带有给定参数名称的函数kw,很可能你可以简单地编写代码,也许可以使用locals()紧要关头。

def process(**kw):
  print 'Value of foo is %s' % (kw['foo'],)
  print 'Value of bar is %s' % (kw['bar'],)

process(foo=2, bar=3)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何动态修改函数的本地命名空间? 的相关文章

随机推荐

  • 如何在 C++ 中可移植地计算 sha1 哈希值?

    目标是计算SHA1作为 C 程序一部分的一个或多个缓冲区的哈希值 我不确定使用 boost 的 UUID 是否会正确地在哈希值中添加前导零 据我所知 您的字符串应该始终具有相同的长度 因此这里是上面示例的简化版本 可以做到这一点 inclu
  • css3 动画停止

    目前我正在制作带有滑块动画的标题 仅限 css3 http jimmytenbrink nl slider 一切工作正常 除了有时从中心向右移动时滑块会出现故障 看来我需要停止动画几毫秒才能完成 然而 我在互联网上到处搜索 但似乎无法让它工
  • 无法访问 Metro 应用中的资产文件

    我正在尝试读取一个文本文件 该文件作为 Metro 应用程序中的资产提供 如果将文件路径指定为 ms appx Assets file txt 我会收到访问被拒绝错误 显然我需要设置一些访问安装位置文件夹的功能 我尝试启用清单设计器中的所有
  • Visual Studio 安装和部署构建失败,没有错误

    我有一个设置和部署项目 在我们的构建服务器上 在摘要中报告以下内容 全部重建 25 成功 2 失败 0 跳过 我不知道失败的两个是什么 但我相信其中之一是 vdproj 项目 因为如果我在没有安装程序的情况下运行构建 则根本不会报告任何错误
  • 如何用PHP下载大文件?

    我花了一周的时间来找到这个问题的正确答案 Right 我的意思是绝对符合现有的网络标准 可靠且性能有效 最后 我找到了解决方案 我在 StackOverflow 上找到的所有内容 在 PHP 中可靠地下载大文件 如何通过PHP脚本下载大文件
  • 使用 Quartz.NET 3.0.3 和简单注入器进行构造函数注入操作方法

    我正在尝试在 Windows 服务中使用 Quartz Net v3 0 3 和简单注入器 我有一个作业类 我想在其下面注入一些依赖项 例如我的记录器 public class JobWorker IJob private ILogger
  • 向按钮添加彩色阴影

    我需要向具有 来自 zeplin 这些属性的按钮添加阴影 这就是设计 我试过这段代码
  • React 中生成器的调用次数超出预期

    我发现生成器似乎被调用两次的行为 下面是一个简单的代码 它从生成器获取一个数字并将其输出到控制台 它期望控制台输出 0 和 1 但实际上输出的是 0 和 2 import useState useEffect from react func
  • <%= 导轨 4 中有一个块

    我正在尝试在助手中使用块 但这给了我这个错误 SyntaxError syntax error unexpected rbout concat green title do to s erbout concat n erb 4254 syn
  • 大多数静态数据流的 CRC 计算

    背景 我有一段内存 1024字节 最后 1020 字节始终相同 前 4 个字节将发生变化 产品的序列号 我需要计算CRC 16 CCITT 0xFFFF 起始 0x1021 掩码 对于整个内存部分 CRC WHOLE 问题 是否可以仅计算前
  • 如何在 XAML 中绑定到静态属性?

    我试图将不同类的静态属性绑定到 TextBlock 的 Text 属性 并且可以使绑定正常工作 但是当静态属性的值发生更改时 Text 属性不会更新 我读过 我无法使用 INotifyPropertyChanged 因为该属性是静态的 并且
  • 导航推送新的根控制器

    我正在尝试将新的根控制器推送到导航堆栈 但使用侧面显示菜单 我的应用程序委托具有以下内容 welcomeViewController MyWelcomeViewController alloc initWithNibName MyWelco
  • ORACLE 中的利斯塔格

    我正在尝试使用 LISTAGG 来获取两列以上 SELECT deptname deptno LISTAGG ename WITHIN GROUP ORDER BY ename AS employees FROM emp GROUP BY
  • 在 $0 和 BASH_SOURCE 之间选择

    一个人如何选择 0 and BASH SOURCE 0 这段描述来自GNU对我帮助不大 BASH SOURCE An array variable whose members are the source filenames where t
  • 在 OCaml 中组合一列列表

    我想在 OCaml 中转置一个矩阵 不使用递归或任何类型的循环 例如 如果我有以下矩阵 1 2 3 4 我想要的输出 1 3 2 4 到目前为止我所做的是将原始矩阵分解为单独的列 function that separates into c
  • HTML5 是否使 Javascript 游戏更安全(更安全)?

    我知道 JavaScript 是一种极其不安全的持久游戏编程方式 例如 您在 RPG 中进行战斗计算 然后在获胜时通过链接到 PHP 页面来奖励 XP 该页面会将 XP 添加到数据库中 因为玩家可以制作自己的 javascript 来始终获
  • WPF 树数据模板取决于项目类型

    我有一个 MVVM WPF 应用程序 其中有一棵包含自引用数据的树 该数据通过分层转换器绑定到该树 如示例 http www telerik com help wpf radtreeview how to bind to self refe
  • Android WebView 与layer_type_software 不显示HTML5 画布内容

    自上次更新 Android WebView 以来 通过将 WebView 的图层类型设置为 View LAYER TYPE SOFTWARE 来禁用硬件加速时 带有 HTML5 画布的网页无法正确显示 这个问题有解决方法吗 当我省略以下 J
  • 构建 VSCode 和 Android Studio (Flutter) 的 gradle 时配置根项目“android”时出现问题

    今天开始学习Flutter 并成功下载了所有东西 但是当我运行我的应用程序时 调试器 两者VSCode and Android Studio 给我这个错误 Launching lib main dart on sdk gphone x86
  • 如何动态修改函数的本地命名空间?

    注意 这个问题假设 Python 2 7 3 我正在寻找一种合理的方法来动态修改函数的本地命名空间 最好以一种给函数体函数添加最少混乱的方式 我的想法是这样的 import os from namespace updater import