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

时间:2018-12-26 20:16:15

标签: python anonymous-function

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

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

但是此功能要按字典组织:

my_functions = {
    ....
}

很明显,我可以编写以下语句将此功能添加到字典中:

my_functions['write_one'] = write_one

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

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

使用del write_one的解决方案在我看来并不好。我根本不想在当前名称空间中引入这个名称。

总而言之,我想要的是这样的

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

我知道,这与Python基于缩进的规则有点尴尬。但这确实可以做到。

2 个答案:

答案 0 :(得分:4)

Lambda表达式的功能受到很大限制。从docs

  

请注意,使用lambda表达式创建的函数不能包含语句或注释。

只需使用完整的函数定义。如果您确实想避免污染名称空间,则之后只需del即可。

或者,如果您只是想避免模块名称空间包含一堆用于代码完成的小功能,请在函数名称前面使用_

如果您确实想避免这种情况,可以可以使用function构造函数并动态编译代码,等等。或者使用其他某种动态代码执行方法,例如使用evalexec。但这几乎是不值得的。  尤其是在使用完del之后,只要 const myPromisedFunction = () => { console.log('my promised function'); return new Promise((resolve, reject) => { setTimeout(() => resolve, 1000); }); }; myPromisedFunction().then(() => myPromisedFunction()).then(() => console.log('done')); 即可。

也许最好的方法是将所有这些功能放在另一个名称空间中,例如另一个模块。

答案 1 :(得分:1)

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

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