【问题标题】:python: `with` statement in anonymous functionspython:匿名函数中的`with`语句
【发布时间】:2018-12-26 20:16:15
【问题描述】:

是否可以在 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 的基于缩进的规则有点尴尬,我知道。但它确实发挥了作用。

【问题讨论】:

  • 不,不是。 lambda 表达式只能包含表达式,不能包含语句。
  • @juanpa.arrivillaga lambda 是在 Python 中构造匿名函数的唯一方法吗?我说的是匿名函数而不是 lambda
  • 是的。我很少使用lambda 表达式,只有在我超级懒惰的时候,或者对于我传递给像map这样的高阶函数的非常简单的一次性操作@
  • @juanpa.arrivillaga 那么文档在哪里说 lambda 是构造匿名函数的唯一方法
  • 是的。或者你可以相信有语言经验的人。由你决定。

标签: python anonymous-function


【解决方案1】:

Lambda 表达式的功能非常有限。来自docs

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

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

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

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

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

【讨论】:

  • 顺便说一句,我绝不赞同这一点,它可能会让你有点恼火,这有一个 hack - 使用exec。现在这是虫子的秘诀!或者为此删除硬盘。
  • @kabanus 当然,我已经添加了这些高度 hacky 的选项作为编辑。
  • 啊我现在明白了 - 有点不同意“函数中的函数”是 hacky,但其余的我完全同意。
  • @kabanus 我不是那个意思,我的意思是使用evalexecfunction 构造函数
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2013-07-19
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    相关资源
    最近更新 更多