我最近发现了Ruby的块和屈服特征,我想知道:这在计算机科学理论方面适合哪些方面?它是一种函数式编程技术,还是更具体的?
假设我有一个列表,我希望不返回,但要从中产生值.什么是最pythonic的方式呢?
这就是我的意思.由于一些非惰性计算我已经计算了列表['a', 'b', 'c', 'd'],但我的代码通过项目使用延迟计算,所以我想从我的函数中产生值而不是返回整个列表.
我目前写的如下:
my_list = ['a', 'b', 'c', 'd']
for item in my_list:
yield item
Run Code Online (Sandbox Code Playgroud)
但这对我来说并不像是pythonic.
我使用了很多yield return关键字,但是当我想要添加一个范围时,我发现它缺乏IEnumerable.这是我想做的一个简单示例:
IEnumerable<string> SomeRecursiveMethod()
{
// some code
// ...
yield return SomeRecursiveMethod();
}
Run Code Online (Sandbox Code Playgroud)
当然这会导致错误,可以通过简单的循环来解决.有一个更好的方法吗?一个循环感觉有点笨重.
考虑一下混淆代码.目的是通过匿名构造函数及其动态创建一个新对象yield return.目标是避免仅仅为了维护本地集合return.
public static List<DesktopComputer> BuildComputerAssets()
{
List<string> idTags = GetComputerIdTags();
foreach (var pcTag in idTags)
{
yield return new DesktopComputer() {AssetTag= pcTag
, Description = "PC " + pcTag
, AcquireDate = DateTime.Now
};
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这段代码会产生异常:
错误28'Foo.BuildComputerAssets()'的主体不能是迭代器块,因为'System.Collections.Generic.List'不是迭代器接口类型
问题
yield return正确使用?我有一个功能,可以在下载时产生结果.出于这个问题的目的,让我说我每秒产生一次刺痛,但我想要一个方便函数来包装我的生成器:
import time
def GeneratorFunction(max_val):
for i in range(0,5):
time.sleep(1)
yield "String %d"%i
def SmallGenerator():
yield GeneratorFunction(3)
for s in SmallGenerator():
print s
Run Code Online (Sandbox Code Playgroud)
...为什么不打印出我期待的5根弦?相反,它似乎返回生成器函数:
<generator object GeneratorFunction at 0x020649B8>
Run Code Online (Sandbox Code Playgroud)
如何让这个产生字符串作为普通的生成器函数?
我有一个线程正在轮询一块硬件.
while not hardware_is_ready():
pass
process_data_from_hardware()
Run Code Online (Sandbox Code Playgroud)
但是还有其他线程(和进程!)可能有事情要做.如果是这样,我不想每次其他指令都烧掉cpu检查硬件.自从我处理线程以来已经有一段时间了,当我这样做时它不是Python,但我相信大多数线程库都有一个yield函数或某些东西允许线程告诉调度程序"给其他线程一个机会".
while not hardware_is_ready():
threading.yield() # This function doesn't exist.
process_data_from_hardware()
Run Code Online (Sandbox Code Playgroud)
但我在线程文档中找不到任何类似的引用.Python确实有一个yield声明,但我很确定这完全是另一回事(与生成器有关).
在这做什么是正确的?
我想使用生成器产量和异步函数.我读了这个主题,并编写了下一个代码:
import asyncio
async def createGenerator():
mylist = range(3)
for i in mylist:
await asyncio.sleep(1)
yield i*i
async def start():
mygenerator = await createGenerator()
for i in mygenerator:
print(i)
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(start())
except KeyboardInterrupt:
loop.stop()
pass
Run Code Online (Sandbox Code Playgroud)
但我得到了错误:
SyntaxError:异步函数内的'yield'
如何在异步函数中使用yield生成器?
我有一个采用代码块的方法.
def opportunity
@opportunities += 1
if yield
@performances +=1
end
end
Run Code Online (Sandbox Code Playgroud)
我称之为:
opportunity { @some_array.empty? }
但是我如何传递多个代码块以便我可以使用yield两次,如下所示:
def opportunity
if yield_1
@opportunities += 1
end
if yield_2
@performances +=1
end
end
Run Code Online (Sandbox Code Playgroud)
和:
opportunity {@some_other_array.empty?} { @some_array.empty? }
Run Code Online (Sandbox Code Playgroud)
我知道这个例子可以在没有收益的情况下完成,但这只是为了说明.
我有一个产生的方法,看起来像:
def a_method(*params)
# do something
yield
# do something else
end
Run Code Online (Sandbox Code Playgroud)
如果传入一个块,我希望这个方法产生块; 并且如果没有传入块,该方法应该轻易地跳过yield sentense而不会崩溃,例如:
no block given (yield) (LocalJumpError)
Run Code Online (Sandbox Code Playgroud)
当然,最直接的方法是将方法更改为:
def a_method(*params, &block)
# do something
yield if block
# do something else
end
Run Code Online (Sandbox Code Playgroud)
但是不是更漂亮的方式吗?
在我不断追求吸吮的过程中,我试图理解"收益"陈述,但我一直遇到同样的错误.
[someMethod]的主体不能是迭代器块,因为'System.Collections.Generic.List <AClass>'不是迭代器接口类型.
这是我遇到的代码:
foreach (XElement header in headersXml.Root.Elements()){
yield return (ParseHeader(header));
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我不能在迭代器中使用yield吗?那有什么意义呢?在这个例子中,它说它List<ProductMixHeader>不是迭代器接口类型.
ProductMixHeader是一个自定义类,但我想List是一个迭代器接口类型,不是吗?
- 编辑 -
感谢所有快速解答.
我知道这个问题不是全新的,同样的资源不断涌现.
事实证明我认为我可以List<AClass>作为返回类型返回,但由于List<T>不是懒惰,它不能.更改我的返回类型以IEnumerable<T>解决问题:D
一个有点相关的问题(不值得打开一个新线程):IEnumerable<T>如果我确定99%的情况我将要去.ToList(),它是否值得作为返回类型给出?性能影响是什么?