如何在with语句中创建局部变量?

时间:2015-07-22 09:49:26

标签: python python-2.7

我想在有限的范围内创建可见的临时变量。 在我看来,你可以使用"和#34;声明,我认为有一个结构可以让它变得容易,但我似乎无法找到它。

我想要类似下面的内容(但当然不会这样做):

pronunciation = "E_0 g z @_1 m p l"
# ...
with pronunciation.split() as phonemes:
    if len(phonemes) > 2 or phonemes[0].startswith('E'):
        condition = 1
    elif len(phonemes) < 3 and phonemes[-1] == '9r':
        condition = 2

有没有一种简单的方法可以使用内置函数来完成这项工作?

谢谢!

5 个答案:

答案 0 :(得分:2)

Python使用函数作用域创建局部变量(一旦使用了名称,它将保持活动直到函数结束)。

如果你真的想限制范围,那么“del&lt; var&gt;”当你想要它被明确地丢弃时,或者创建单独的函数来充当更有限范围的容器。

答案 1 :(得分:2)

您可以创建方法

def process_pronunciation(pronunciation):
    phonemes = pronunciation.split()
    if len(phonemes) > 2 or phonemes[0].startswith('E'):
        condition = 1
    elif len(phonemes) < 3 and phonemes[-1] == '9r':
        condition = 2
    return condition

调用方法时,局部变量phonemes在全局命名空间中不可用。

pronunciation = "E_0 g z @_1 m p l"
condition = process_phonemes(pronunciation)

答案 2 :(得分:1)

你可以用with来做,但我认为这不值得。基本上(在python函数中)你有两个范围 - 全局或本地,就是这样。如果您希望符号的寿命比函数短,则必须使用del将其删除。您可以定义自己的上下文管理器来实现此目的:

class TempVar:
     def __init__(self, loc, name, val):
          self.loc = loc
          self.name = name
          self.val

     def __enter__(self):
          if self.name in self.loc:
              self.old = self.loc[self.name]
          self.loc[self.name] = self.val

     def __exit__(self, *exc):
          if hasattr(self, "old"):
              self.loc[self.name] = self.old
          else:
              del self.loc[self.name]

然后你可以用它来获得一个临时变量:

with TempVar(locals(), "tempVar", 42):
    print(tempVar)

工作是它在进入时修改包含dict局部变量(通过locals()提供给构造函数)并在离开时恢复它。请注意,这取决于修改locals()返回的结果实际修改了本地命名空间 - 规范不保证这种行为。

另一个(更安全的)替代方案是你可以定义一个具有自己范围的独立函数。请记住,嵌套函数是完全合法的。例如:

def outer():
    def inner(tempVar):
         # here tempVar is in scope
         print(tempVar)

    inner(tempVar = 42)

    # here tempVar is out of scope

答案 3 :(得分:0)

with语句没有自己的作用域,它使用周围的作用域(如果with语句直接在脚本内部,而不是在任何函数内,它使用全局名称空间,如果{{1} }语句在函数内部使用,它使用函数的命名空间(范围))。

如果你希望with块中的语句在它自己的本地范围内运行,一种可能的方法是将逻辑移动到一个函数,这样逻辑就会在它自己的范围内运行(而不是周围的范围) with

示例 -

with

请注意,上述内容不会阻止def function_for_with(f): #Do something. with pronunciation.split() as phonemes: function_for_with(phonemes) 在周围范围内定义。

如果你也想要它(将phonemes移动到它自己的范围内),你可以在函数内移动complete with语句。示例 -

phonemes

答案 4 :(得分:0)

扩展@ skyking的答案,这是一个更神奇的实现同样的想法,读取几乎与你写的一样。介绍: with var声明 1

class var:
    def __init__(self, value):
        import inspect
        self.scope = inspect.currentframe().f_back.f_locals
        self.old_vars = set(self.scope.keys())
        self.value = value
    def __enter__(self):
        return self.value
    def __exit__(self, type, value, traceback):
        for name in set(self.scope.keys()) - self.old_vars:
            del self.scope[name]

### Usage:

line = 'a b c'
with var (line.split()) as words:
    # Prints "['a', 'b', 'c']"
    print(words)

# Causes a NameError
print(words)

它为你做了所有令人讨厌的局部变量和名称提取!怎么膨胀。如果你像我一样歪曲它,并在from boring_stuff import *语句中隐藏定义,你甚至可以假装var是所有困惑的同事的关键词。

[1]如果你真的使用它,一只死鹦鹉的幽灵可能永远困扰着你。其他答案提供了更安全的解决方案;这个更像是一个笑话。