Mic*_*ski 11 ruby python idioms
有一个有用的Ruby习惯用法tap允许你创建一个对象,对它做一些操作并返回它(我在这里只使用一个列表作为例子,我真正的代码更多参与):
def foo
[].tap do |a|
b = 1 + 2
# ... and some more processing, maybe some logging, etc.
a << b
end
end
>> foo
=> [1]
Run Code Online (Sandbox Code Playgroud)
使用Rails有一个类似的方法returning,所以你可以写:
def foo
returning([]) do |a|
b = 1 + 2
# ... and some more processing, maybe some logging, etc.
a << b
end
end
Run Code Online (Sandbox Code Playgroud)
这说明了一切.无论你对对象做了多少处理,它仍然清楚它是函数的返回值.
在Python中我必须写:
def foo():
a = []
b = 1 + 2
# ... and some more processing, maybe some logging, etc.
a.append(b)
return a
Run Code Online (Sandbox Code Playgroud)
我想知道是否有办法将这个Ruby成语移植到Python中.我的第一个想法是使用with语句,但return with语法无效.
Muh*_*uri 24
简短回答:Ruby鼓励方法链,而Python则不然.
我想正确的问题是:Ruby tap对什么有用?
现在我对Ruby知之甚少,但通过谷歌搜索,我得到的印象tap是概念上有用的方法链接.
在Ruby中,风格:SomeObject.doThis().doThat().andAnotherThing()非常惯用.例如,它是流畅接口的概念的基础.Ruby tap是一个特殊情况,而不是SomeObject.doThis()你动态定义doThis.
为什么我要解释这一切?因为它告诉我们为什么tap在Python中没有很好的支持.有了适当的警告,Python不会进行调用链接.
例如,Python列表方法通常返回None而不是返回变异列表.函数喜欢map和filter不是列表方法.另一方面,许多Ruby数组方法确实返回修改后的数组.
除了某些ORM之外的某些情况,Python代码不使用流畅的接口.
最后,它是惯用的Ruby和惯用的Python之间的区别.如果您要从一种语言转到另一种语言,则需要进行调整.
您可以在Python中实现它,如下所示:
def tap(x, f):
f(x)
return x
Run Code Online (Sandbox Code Playgroud)
用法:
>>> tap([], lambda x: x.append(1))
[1]
Run Code Online (Sandbox Code Playgroud)
然而,它在Python 2.x中的使用并不像在Ruby中那么多,因为Python中的lambda函数是非常严格的.例如,您无法内联调用print,因为它是一个关键字,因此您无法将其用于内联调试代码.您可以在Python 3.x中执行此操作,尽管它不像Ruby语法那样干净.
>>> tap(2, lambda x: print(x)) + 3
2
5
Run Code Online (Sandbox Code Playgroud)
如果你想要这么糟糕,你可以创建一个上下文管理器
class Tap(object):
def __enter__(self, obj):
return obj
def __exit__(*args):
pass
Run Code Online (Sandbox Code Playgroud)
您可以使用如下:
def foo():
with Tap([]) as a:
a.append(1)
return a
Run Code Online (Sandbox Code Playgroud)
没有绕过return声明,with在这里真的没有做任何事情.但是你Tap在开始时确实有权利,这可以让你知道我想要的功能是什么.它比使用lambdas更好,因为你不仅限于表达式,并且在with语句中可以有你想要的任何东西.
总的来说,我会说,如果你想要tap那么糟糕,那么坚持使用ruby,如果你需要在python中编程,使用python来编写python而不是ruby.当我开始学习ruby时,我打算写ruby;)