什么是Python等价于Ruby的yield?

2024-10-02 20:44:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一个项目从Ruby切换到Python。Python闭包应该是第一个很容易理解的问题。我只是不知道Python的习惯用法是什么:

在Ruby中,我可以写:

def with_quietude(level, &block)
  begin
    saved_gval = gval
    gval = level
    yield
  ensure
    gval = saved_gval
  end
end

这样称呼:

^{pr2}$

(注意:我不是问Python try/finally处理,也不是关于保存和恢复变量的问题——我只是想要一个在其他代码中包装块的简单示例。)

更新

或者,由于在前面的例子中,当我真正询问闭包时,有些答案被挂在了全局赋值上,如果调用如下所示呢?(请注意,这不会改变“安静”的定义):

def frumble(x)
  with_quietude {
    razz_the_jazz(x)
    begin_the_beguine(2 * x)
  }
end

如何在Python中实现类似的东西(而不会被Python专家嘲笑)?在


Tags: the项目defwithblocklevelendruby
3条回答

如果你来自Ruby,那就警告一下:所有python的def基本上都与Ruby的proc相同

Python没有ruby的“def”等价物

通过在调用函数的范围内定义自己的函数,您可以获得与您所要求的非常相似的行为

def quietude(level, my_func):
    saved_gval = gval
    gval = level
    my_func()

def my_func():
  razz_the_jazz()
  begin_the_beguine()

quietude(3, my_func)

编辑:请求更多信息:

Python的lambda仅限于一行,因此它们不像ruby那样灵活

要传递带参数的函数,我建议部分函数请参见以下代码:

^{2}$

编辑2个更多信息

Python函数只有在添加了“()”之后才被调用。这不同于ruby,“()”是可选的。下面的代码在start()中运行“b”方法,在run()中运行“a”方法)

def a_method():
    print 'a_method is running'
    return 'a'

def b_method():
    print 'b_method is running'
    return 'b'

def run(a, b):
    print a()
    print b

def start():
    run(a_method, b_method())

我喜欢mgilson给出的答案,所以它得到了支票。对于来自Ruby世界的人来说,这只是对@contextmanager功能的一个小扩展。在

gval = 0

from contextlib import contextmanager

@contextmanager
def quietude(level):
    global gval
    saved_gval = gval
    gval = level
    try:
        yield
    finally:
        gval = saved_gval

def bebop(x):
  with quietude(3):
    print "first", x*2, "(gval =", gval, ")"
    print "second", x*4, "(gval =", gval, ")"

bebop(100)
bebop("xxxx")

打印出来:

^{2}$

这表明with范围内的所有内容都可以访问词汇上封闭的变量,并且或多或少地表现出来自Ruby世界的人所期望的方式。在

好东西。在

深入研究ruby的收益率,您似乎想要类似^{}

from contextlib import contextmanager

def razz_the_jazz():
    print gval

@contextmanager
def quietude(level):
    global gval
    saved_gval = gval
    gval = level

    try:
        yield
    finally:
        gval = saved_gval

gval = 1

with quietude(3):
     razz_the_jazz()

razz_the_jazz()

此脚本输出:

^{2}$

指示我们的上下文管理器在全局命名空间中重置了gval。当然,我不会使用这个上下文管理器,因为它只在全局名称空间中工作。(它不能在函数中使用局部变量)例如。在

这基本上是对赋值如何创建对对象的新引用的限制,而且您永远不能通过直接赋值来改变对象。(改变一个对象的唯一方法是分配给它的一个属性或通过__setitem__a[x] = whatever))来实现

相关问题 更多 >