-2

我的预期行为是:

>>> x = 0
>>> with (x := 1): print(x)
1
>>> print(x)
0

但是我得到了预期的AttributeError: __enter__错误。有没有一种简单的方法可以实现这一点,或者类似的方法可以让我弥补没有 Lisp 风格的 let 表达式?

PS我知道我可以做类似的事情:

class Let(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    def __enter__(self):
        return self
    def __exit__(self, *args):
        return None

接着:

>>> with Let(x=1) as let: print(let.x)

或者:

>>> with (let := Let(x=1)): print(let.x)

但不得不说let.x,而不是只是x让它太丑陋了!

4

3 回答 3

0

使用您现有的 Let 类,您可以使用 __str__ (根据此答案)更改该类的字符串表示形式。然后只需调用您的实例 'x' 和 print(x) 就可以了

于 2020-02-08T08:32:01.603 回答
0

:=操作与letJavaScript 不同,它是一种将值分配给变量并同时输出值的操作。松散地说,let就是声明一个局部变量,即。您不能在范围之外使用此变量。

我不确定“让表达式”是什么意思,但:=与范围区分分配不同。

于 2020-02-08T08:25:18.347 回答
-1

我不知道为什么在发布这个问题之前我没有找到这个(https://nvbn.github.io/2014/09/25/let-statement-in-python/

它的行为就像我想要的那样:

from contextlib import contextmanager
from inspect import currentframe, getouterframes

@contextmanager
def let(**bindings):
    frame = getouterframes(currentframe(), 2)[-1][0]
    locals_ = frame.f_locals
    original = {var: locals_.get(var) for var in bindings.keys()}
    locals_.update(bindings)
    yield
    locals_.update(original)


x = 0

with let(x=1):
    print(x)

print(x)

不过,它需要稍微调整一下。例如,未定义的变量None在 let 中返回,而不是 a NameError

我仍然不知道如何在不将其包装在函数中的情况下进行递归。即类似的东西:

>>> with let(x=1, y=x+1):
       print(x, y)
1 2

输入表示赞赏!

更新

这个答案不能正常工作,因为你不能更新 locals()...好吧,回到第一格。

于 2020-02-08T08:45:33.350 回答