【问题标题】:How can a function set the value of a variable without returning the value of that variable?函数如何设置变量的值而不返回该变量的值?
【发布时间】:2016-02-02 21:29:27
【问题描述】:

我想导入一个特殊且不寻常的模块。为了导入这个模块,我必须为其导入准备环境,导入模块,然后在导入后再次更改环境。我可以这样做的方法如下:

argv_tmp = sys.argv
sys.argv = []
from ROOT import *
sys.argv = argv_tmp

我想将围绕实际导入的过程抽象为两个函数,从而产生以下形式的主代码:

pre_ROOT_import()
from ROOT import *
post_ROOT_import()

这些函数(不带参数且不返回值的函数)如何执行这些过程?

【问题讨论】:

  • 这听起来像是一个计划得很糟糕的模块......它是公开的吗?如果有,是哪一个?
  • 是什么阻止您将这些代码行放入函数中?您是否尝试过并收到错误或意外行为?
  • 使用global关键字

标签: python import root main argv


【解决方案1】:

这样的?我认为只需将 arg_tmp 拉到函数之外就可以了,函数仍然可以访问它。

import sys
argv_tmp = None

def pre_ROOT_import():
  #set argv_tmp and modify sys.argv
def post_ROOT_import():
  #restore sys.argv to argv_tmp

pre_ROOT_import()
from ROOT import *
post_ROOT_import()

【讨论】:

    【解决方案2】:

    这是context manager 的一个非常好的用例。

    class ArgvContext(object):
        def __enter__(self):
            self.tmp_argv = sys.argv
            sys.argv = []
        def __exit__(self, exc_type, exc_val, exc_tb):
            sys.argv = sys.tmp_argv
    

    用法:

    with ArgvContext():
        from ROOT import *
    

    __enter__ 中的代码在上下文之前执行,__exit__ 中的代码在上下文之后执行。这里的上下文仅表示在with 语句下缩进的所有内容。使用self的属性将信息从之前传递到之后。

    一个简单的例子:

    class Context(object):
        def __enter__(self):
            print('start')
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('end')
    
    with Context():
        print('doing')
    

    打印:

    start
    doing
    end
    

    __exit__中的代码在出现异常时也会执行:

    with Context():
        1 / 0
    

    输出:

    start
    end
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
    ...
    ZeroDivisionError: division by zero
    

    【讨论】:

    • @skrrgwasme 还在输入 ;)。
    • 非常感谢您非常清晰、正确和详细的回答。我讨厌这个,但如果我想接受两个答案,我必须去here 试图找出该怎么做。评分最高的答案 (this) 表明我赞成所有正确答案并接受我实际使用的答案或首先出现的答案。我也想接受你的回答,但 StackOverflow 阻止我这样做。非常感谢!
    【解决方案3】:

    上下文管理器在这里工作得很好。它在本地保存 sys.argv 并恢复它,即使在 ROOT 中引发异常也是如此。

    import contextlib
    @contextlib.contextmanager
    def argv_tmp():
        tmp = sys.argv
        sys.argv = []
        try:
            yield
        finally:
            sys.argv = tmp
    
    with argv_tmp():
        from ROOT import *
    

    【讨论】:

    • 我希望我能多次投票。这是上下文管理器的完美用例。
    • 这可以通过将yield 放入try: ... finally: ... 来改进,以确保在发生异常时仍能恢复环境。
    • 非常感谢您的解决方案。它简洁明了。我认为@MikeMüller 提出的the solution 也很好。感谢您向我介绍上下文管理器!
    猜你喜欢
    • 2016-11-25
    • 2022-01-22
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多