我不知道正确的术语.我试图谷歌它,因为这个原因找不到任何东西.
我正在编写一个Ruby库,我想重写这些函数,因此它们的工作方式如下所示,因为我更喜欢它的可读性(块内?)
我有一个功能,这样做
@dwg = Dwg.new("test.dwg")
@dwg.line([0,0,0],[1,1,0])
@dwg.save
Run Code Online (Sandbox Code Playgroud)
我想重写它,所以它的工作方式就像这样
Dwg.new("test.dwg") do
line([0,0,0],[1,1,0])
save
end
Run Code Online (Sandbox Code Playgroud)
你能概括一下我的方式吗?
假设我有一些经理对象.这个对象的API有一个main_hook函数,它获取另一个函数f作为它的参数,并f在循环中运行给定的东西,在每次迭代之间做一些事情:
def main_hook(self,f):
while (self.shouldContinue()):
#do some preparations
f(self)
#do some tear down
Run Code Online (Sandbox Code Playgroud)
现在,我也有(更确切地说,想要)一个函数stop_and_do_stuff,一旦被调用,就停止main_hook在它的轨道中,将控制返回到所调用的函数main_hook,然后在该函数完成它正在做的事情之后,将控制权交还给main_hook和继续.基本上结果与做的一样
def main_hook(self,f):
while (self.shouldContinue()):
#do some preparations
yield
#do some tear down
Run Code Online (Sandbox Code Playgroud)
除此之外,yield我想打电话给f(),同时给出f打电话的选项self.stop_and_do_stuff()
我不能通过使f也成为发电机来解决这个问题有两个原因:
1. f不是我的API的一部分 - 它是由使用我的lib的用户提供给我的
2.即使可以要求他使用yield,他需要调用的代码中的位置stop_and_do_stuff也不会直接位于f内,而是位于函数堆栈中的某个位置f(),而不是直接位于其中,例如
def h(manager):
#do stuff
if should stop:
manager.stop_and_do_stuff()
#do more stuff
def g(manager):
#some stuff
if should stop:
manager.stop_and_do_stuff() …Run Code Online (Sandbox Code Playgroud) 我在测试中有一个奇怪的行为,我想测试当作为参数传入null时抛出异常.当我运行测试时,我从NUnit获得:
System.ArgumentNullException was expected
-- Exception doesn't have a stack trace --
Run Code Online (Sandbox Code Playgroud)
我的测试:
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void Should_not_retrieve_any_fields_when_file_is_null()
{
_creator.CreateFields(null);
}
Run Code Online (Sandbox Code Playgroud)
我的实施:
public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file)
{
if (file == null) throw new ArgumentNullException("file");
using (var reader = new StreamReader(file.InputStream))
{
var firstLine = reader.ReadLine();
var columns = firstLine.Split(new[] { ',' });
for (var i = 0; i < columns.Length; i++)
{
yield return new ImportField(columns[i], i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种行为是否有合理的解释,我应该以不同的方式实现我的实现吗?
在这段代码中,我想增加index它以将它放到每个yield结果中.
var index=0
for(str <- splitToStrings(text) ) yield {
if (index != 0) index += 1 // but index is equal to `0` all the time
new Word(str, UNKNOWN_FORM, index )
}
Run Code Online (Sandbox Code Playgroud)
为什么我不能改变index?那么实现这种逻辑的最佳方法是什么,试图简洁?
更新:示例现在列出所需的结果(下方以粗体显示)
我发现自己编写了许多搜索一些数据的函数,我想让调用者在找到匹配项时指定行为:它们可能会打印出一些内容或将其添加到其中一个数据结构中,但也非常希望能够可选地返回找到的数据以进一步传输,存储或处理.
def find_stuff(visitor): # library search function
for x in (1, 2, 3, 4, 5, 6):
visitor(x)
Run Code Online (Sandbox Code Playgroud)
首次客户使用:
def my_visitor(x): # client visitor functions (also often use lambdas)
if x > 3:
yield x / 2 #>>> WANT TO DO SOMETHING LIKE THIS <<<#
results = find_stuff(my_visitor) # client usage
Run Code Online (Sandbox Code Playgroud)
results 应该产生4/2,5/2,然后是6/2 ......即2,2,3.
第二个客户使用:
def print_repr_visitor(x):
print repr(x)
find_stuff(print_repr_visitor) # alternative usage
Run Code Online (Sandbox Code Playgroud)
应打印1 2 3 4 5 6(单独的行)但不产生任何结果
但是,它yield并没有在"结果"中创建一个生成器(至少使用python 2.6.6,我坚持使用).
我一直在乱砍这个,经常这样......
def find_stuff(visitor):
for x …Run Code Online (Sandbox Code Playgroud) 根据Python文档,yield关键字可以采用" expression_list ",但它是可选的:
yield_expression ::= "yield" [expression_list]
Run Code Online (Sandbox Code Playgroud)
我不能在Python文档中找到这样的用法的例子,在关于yield关键字在Python中做什么的任何答案,也不是在网上阅读.
如果yield没有使用,expression_list那么我猜测结果方法不能用作生成器,那么平原yield可能有用吗?
在Ruby中,yield关键字用于产生执行块的闭包.
这个关键字在Python语言中有何不同?
在Ruby中,lambda使用错误数量的参数调用a会导致ArgumentError:
l = lambda { |a, b| p a: a, b: b }
l.call(1, 2)
# {:a=>1, :b=>2}
l.call(1)
# ArgumentError: wrong number of arguments (given 1, expected 2)
Run Code Online (Sandbox Code Playgroud)
传递数组也不起作用:(因为数组只是一个对象,对吧?)
l.call([3, 4])
# ArgumentError: wrong number of arguments (given 1, expected 2)
Run Code Online (Sandbox Code Playgroud)
除非我使用splat(*)将数组转换为参数列表,否则我没有.
但是 ......如果我通过隐式调用lambda yield,会发生意外情况:
def yield_to
yield(1, 2)
yield([3, 4])
end
yield_to(&l)
# {:a=>1, :b=>2}
# {:a=>3, :b=>4} <- array as argument list!?
Run Code Online (Sandbox Code Playgroud)
更令人困惑的是,lambda派生的via Method#to_proc会按预期工作:
def m(a, b)
p a: …Run Code Online (Sandbox Code Playgroud) 从python函数中产生时如何连接两个项?
基本情况:
import itertools
def test():
for number in range(0,10):
yield number
list(test()) # [0...9]
Run Code Online (Sandbox Code Playgroud)
如果我想同时得到number它的正方形怎么办?number**2
import itertools
def test():
for number in range(0,10):
yield itertools.chain.from_iterable([
number,number*2
])
list(test())
# [0,0,1,1,2,4,3,9,...] pretended
# <itertools.chain at 0x135decfd0> ... what I got
Run Code Online (Sandbox Code Playgroud)
但是,itertools.chain.from_iterable([generator1, generator2])从外部做,给出了预期的结果.
def first_list():
for number in range(0,5):
yield number
def second_list():
for number in range(5,10):
yield number
list(itertools.chain.from_iterable([first_list(), second_list()]))
Run Code Online (Sandbox Code Playgroud)