相当于Ruby中的Python"with"

Cla*_*diu 12 ruby python language-features with-statement control-flow

在Python中,该with语句用于确保始终调用清理代码,无论抛出异常还是返回函数调用.例如:

with open("temp.txt", "w") as f:
    f.write("hi")
    raise ValueError("spitespite")
Run Code Online (Sandbox Code Playgroud)

在这里,即使引发了异常,文件也会关闭.这里有一个更好的解释.

Ruby中有这个构造的等价物吗?或者你可以编写一个代码,因为Ruby有延续吗?

Jör*_*tag 22

Ruby对文字匿名过程(在Ruby中称为)具有语法轻量级支持.因此,它不需要新的语言功能.

(一般来说,如果你需要添加语言功能,这是一个不好的标志.你应该能够在库中实现所有内容,否则它是语言设计不良的标志.)

所以,你通常做的是编写一个方法,它接受一段代码,分配资源,在该资源的上下文中执行代码块,然后关闭资源.

像这样的东西:

def with(klass, *args)
  yield r = klass.open(*args)
ensure
  r.close
end
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

with File, 'temp.txt', 'w' do |f|
  f.write 'hi'
  raise 'spitespite'
end
Run Code Online (Sandbox Code Playgroud)

但是,这是一种非常程序化的方法.Ruby是一种面向对象的语言,这意味着在a的上下文中正确执行代码块的责任File应属于File该类:

File.open 'temp.txt', 'w' do |f|
  f.write 'hi'
  raise 'spitespite'
end
Run Code Online (Sandbox Code Playgroud)

这可以实现如下:

def File.open(*args)
  f = new(*args)
  return f unless block_given?
  yield f
ensure
  f.close if block_given?
end
Run Code Online (Sandbox Code Playgroud)

这是一个通用模式,由Ruby核心库,标准库和第三方库中的许多类实现.


与通用Python上下文管理器协议的更紧密的对应关系是:

def with(ctx)
  yield ctx.setup
ensure
  ctx.teardown
end

class File
  def setup; self end
  alias_method :teardown, :close
end

with File.open('temp.txt', 'w') do |f|
  f.write 'hi'
  raise 'spitespite'
end
Run Code Online (Sandbox Code Playgroud)

请注意,这几乎与Python示例无法区分,但它不需要在语言中添加新语法.

  • Ruby拥有*比python更多的*多余的语言特性 - 块上面的`with`的存在使得它下面的所有内容的上下文非常清晰. (4认同)
  • +1能够动态地将其添加到语言中(以及如此少量的代码)非常酷.我认为在语言中也有一个丰富的语法也有一个优点.每个Python开发人员都知道Python中的"with"含义,并且在Python网站/书籍上有详细记录. (2认同)
  • 抱歉,但我不同意"在文件上下文中正确执行代码块的责任应该属于File类".这不是Python,Java或C#,甚至是Objective-C的工作原理,我认为这些语言几乎都是面向对象的.不要误会我的意思,我可以看到这种说法的"美",我也尊重"红宝石的方式".但这正是它的本质:一种美好,优雅,极具活力和表现力的做事方式,而不是"OO"方式.实际上,这与函数式编程有很大关系,而不是OO. (2认同)

Ed *_* S. 9

Ruby中的等价物是将块传递给File.open方法.

File.open(...) do |file|
  #do stuff with file
end  #file is closed
Run Code Online (Sandbox Code Playgroud)

这是Ruby使用的成语,也是你应该习惯的成语.

  • 我不太了解Python,但它看起来像C#的'using'语句.在Ruby中没有像这样的语法糖,但是许多库类实现了如上所示的方法. (4认同)