我有以下代码:
private Dictionary<object, object> items = new Dictionary<object, object>;
public IEnumerable<object> Keys
{
get
{
foreach (object key in items.Keys)
{
yield return key;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是线程安全的吗?如果不是我必须lock围绕循环或yield return?
这就是我的意思:
KeysThread1 访问属性,而Thread2将一个项添加到基础字典.Thread1是否受Thread2的影响?
使用yield关键字来实现这里所示的简单状态机是否可行.对我来说,看起来C#编译器为您完成了艰苦的工作,因为它在内部实现了状态机以使yield语句有效.
你可以在编译器已经完成的工作之上捎带并让它为你实现大部分状态机吗?
有没有人这样做,技术上可行吗?
我是Scala的新手,据我所知,Scala中的收益与C#中的收益不同,它更像是选择.
Scala有类似于C#的收益吗?C#的收益很好,因为它使编写迭代器变得非常容易.
更新:这是来自C#的伪代码示例,我希望能够在Scala中实现:
public class Graph<T> {
public IEnumerable<T> BreadthFirstIterator() {
List<T> currentLevel = new List<T>();
currentLevel.add(_root);
while ( currentLevel.count > 0 ) {
List<T> nextLevel = new List<T>();
foreach( var node in currentLevel ) {
yield return node;
nextLevel.addRange( node.Children );
}
currentLevel = nextLevel;
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码实现了图的迭代广度优先遍历,使用yield,它返回一个迭代器,以便调用者可以使用常规for循环遍历图,例如:
graph.BreadthFirstIterator().foreach( n => Console.WriteLine( n ) );
Run Code Online (Sandbox Code Playgroud)
在C#中,yield只是语法糖,可以很容易地编写迭代器(IEnumerable<T>在.Net中,类似于IterableJava).作为迭代器,它的评估很懒散.
更新II:我可能在这里错了,但我认为C#中的整个收益点是你不必编写更高阶函数.例如,你可以编写一个常规for循环或使用像select/ map/ filter/ 这样的方法,where而不是传入一个函数,然后遍历序列.
如graph.iterator().foreach(n => println(n))代替graph.iterator( …
我正在尝试创建一个实用程序类来遍历目录中的所有文件,包括子目录和子子目录中的文件.我试图使用发电机,因为发电机很酷; 但是,我遇到了麻烦.
def grab_files(directory):
for name in os.listdir(directory):
full_path = os.path.join(directory, name)
if os.path.isdir(full_path):
yield grab_files(full_path)
elif os.path.isfile(full_path):
yield full_path
else:
print('Unidentified name %s. It could be a symbolic link' % full_path)
Run Code Online (Sandbox Code Playgroud)
当生成器到达目录时,它只是产生新生成器的内存位置; 它没有给我目录的内容.
如果已经有一个简单的库函数来递归列出目录结构中的所有文件,请告诉我它.我不打算复制库函数.
我有两个函数返回一个函数列表.函数接受一个数字x并添加i到它.i是一个从0-9增加的整数.
def test_without_closure():
return [lambda x: x+i for i in range(10)]
def test_with_yield():
for i in range(10):
yield lambda x: x+i
Run Code Online (Sandbox Code Playgroud)
我希望test_without_closure返回一个包含10个函数的列表,每个函数都添加9到x自i的值以来9.
print sum(t(1) for t in test_without_closure()) # prints 100
Run Code Online (Sandbox Code Playgroud)
我希望它test_with_yield也会有相同的行为,但它正确地创建了10个函数.
print sum(t(1) for t in test_with_yield()) # print 55
Run Code Online (Sandbox Code Playgroud)
我的问题是,在Python中屈服形成一个闭包吗?
我正在玩迭代,更具体地说是yieldPython中的运算符.在使用测试驱动开发来开始编写新的可迭代时,我想知道什么是最短的代码可以使迭代的这个简单测试通过:
def test():
for x in my_iterable():
pass
Run Code Online (Sandbox Code Playgroud)
我能想到的最短版本是:
def my_iterable():
for i in []:
yield i
Run Code Online (Sandbox Code Playgroud)
是否可以编写更简单,更短或更漂亮(pythonic)的版本?
在Tornado中,我们通常编写以下代码来异步调用函数:
class MainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def post(self):
...
yield self.handleRequest(foo)
...
@tornado.gen.coroutine
def handleRequest(self, foo):
...
Run Code Online (Sandbox Code Playgroud)
但是在asyncio中(将随Python 3.4一起提供,可以从pip for Python 3.3安装),我们yield from用来实现同样的目的:
@asyncio.coroutine
def myPostHandler():
...
yield from handleRequest(foo)
...
@asyncio.coroutine
def handleRequest(foo)
...
Run Code Online (Sandbox Code Playgroud)
从代码看,差异是yield和yield from.然而,前者handleRequest(foo)返回一个tornado.concurrent.Future对象,后者返回一个generator对象.
我的问题是,机制中两件事之间有什么区别?控制流程如何?谁调用实际handleRequest并检索其返回值?
附加:我具有Python生成器和迭代器的基本知识.我想通过使用这些来了解Tornado和asyncio的成就,以及这两种机制之间的区别.
这两种方法的优点/缺点是什么?
return items.Select(item => DoSomething(item));
Run Code Online (Sandbox Code Playgroud)
与
foreach(var item in items)
{
yield return DoSomething(item);
}
Run Code Online (Sandbox Code Playgroud)
编辑因为他们是MSIL大致相当,你发现哪一个更具可读性?
我在django.template中有以下代码:
class Template(object):
def __init__(self, template_string, origin=None, name='<Unknown Template>'):
try:
template_string = smart_unicode(template_string)
except UnicodeDecodeError:
raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.")
if settings.TEMPLATE_DEBUG and origin is None:
origin = StringOrigin(template_string)
self.nodelist = compile_string(template_string, origin)
self.name = name
def __iter__(self):
for node in self.nodelist:
for subnode in node:
yield subnode
def render(self, context):
"Display stage -- can be called many times"
return self.nodelist.render(context)
Run Code Online (Sandbox Code Playgroud)
我困惑的部分如下.这种__iter__方法有什么用?我找不到任何相应的next方法.
def __iter__(self):
for node in self.nodelist:
for subnode …Run Code Online (Sandbox Code Playgroud) 作为一个人为的例子:
myset = set(['a', 'b', 'c', 'd'])
mydict = {item: (yield ''.join([item, 's'])) for item in myset}
Run Code Online (Sandbox Code Playgroud)
并list(mydict)给出:
['as', 'cs', 'bs', 'ds', {'a': None, 'b': None, 'c': None, 'd': None}]
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?怎么yield办?无论表达式yield如何,这种行为是否一致?
注意:我知道做的mydict = {item: ''.join([item, 's']) for item in myset}会给字典{'a': 'as', 'b': 'bs', 'c': 'cs', 'd': 'ds'},这似乎是我想在这里做的.