python: 匿名函数中的`with`语句

python: `with` statement in anonymous functions

是否可以在 Python 匿名函数中使用 with 语句?例如,我有一个将 1 写入文件的函数:

def write_one(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

但是这个函数要组织成一个dict:

my_functions = {
    ....
}

显然我可以写这个语句来将这个函数添加到字典中:

my_functions['write_one'] = write_one

但问题是名称 write_one 仍然存在于当前作用域中。如何在不污染当前命名空间的情况下引入匿名函数?

对于简单的函数,我可以使用lambda。对于稍微复杂的功能,我可以return一个元组来执行多条语句(准确的说是表达式)。但是我没有找到巧妙地使用 lambda 以便它可以与 with 语句一起使用的方法。如果这是不可能的,它在其文档中是这样说的吗?

带有 del write_one 的解决方案对我来说不太好。我不希望在当前命名空间中引入这个名称。

一句话,我想要的是这样的:

my_functions['write_one'] = def(filename):
    with open(filename, 'wt') as fp:
        fp.write('1')

我知道,Python 基于缩进的规则有点尴尬。但它完成了它的工作。

Lambda 表达式的作用非常有限。来自 docs

Note that functions created with lambda expressions cannot contain statements or annotations.

只需使用完整的函数定义。如果你真的想避免污染命名空间,只需 del 之后的名称。

或者,如果您只是想避免模块命名空间有一堆这些用于代码完成目的的小函数,请在函数名称前面使用 _

如果你真的想避免它,你可以使用function构造函数并动态编译代码等。或者使用其他类型的动态代码执行,例如使用 evalexec。但这几乎肯定不值得麻烦。 特别是如果你可以 del 在你使用完它之后的名字。

或许最好的方法是将所有这些函数放在另一个命名空间中,就像另一个模块一样。

Python中的命名空间不多——一个函数基本上就是本地的。这为可能的解决方案提供了一个很好的提示:

def gen_functions():
    def f1(i):
        print(i)
    def f2(i):
        print(i+1)
    return f1,f2

my_funcs = dict(zip(('a','b'),gen_functions()))
my_funcs['a'](2)
my_funcs['b'](7)
f1(3)

运行 这个:

>py bla.py
2
8
Traceback (most recent call last):
  File "bla.py", line 11, in <module>
    f1(3)
NameError: name 'f1' is not defined

因此您可以创建任意复杂的函数 - 要将它们隐藏在全局命名空间中,您只需将它们包含在另一个函数中即可。