【问题标题】:Difference between yield in Python and yield in C#Python中的yield和C#中的yield之间的区别
【发布时间】:2010-12-14 20:18:24
【问题描述】:

Python中的yield关键字和C#中的yield关键字有什么区别?

【问题讨论】:

    标签: c# python


    【解决方案1】:

    C# 的 yield return 相当于 Python 的 yield ,而 yield break 在 Python 中只是 return

    除了那些细微的差别之外,它们的用途基本相同。

    【讨论】:

    • C# 中的 yield break 并不完全等同于 Python 的 return。如果你的函数除了 yield break(Python 中的 return)什么都不做,你会得到一个空的 Enumerator 而在 python 中是一个 None。
    • 这是 Python 的一个小语法怪癖;你可以使用return; yield 来获取一个空的生成器。
    • 另外,Python 中的yield 是一个可以从迭代站点接收值的表达式。 yield return 是一个声明。
    • 但是在 C# 中没有收益,这非常可悲。为了模拟类似的行为,有很多样板代码无法放入函数中。 编辑:如果你使用 Unity,它确实有嵌套的协程!
    【解决方案2】:

    最重要的区别是python yield 给你一个迭代器,一旦它完全迭代就结束了。

    但是 C# yield return 为您提供了一个迭代器“factory”,您可以将它传递并在代码的多个位置使用它,而无需考虑它之前是否已“循环”过一次。

    以python为例:

    In [235]: def func1():
       .....:     for i in xrange(3):
       .....:         yield i
       .....:
    
    In [236]: x1 = func1()
    
    In [237]: for k in x1:
       .....:     print k
       .....:
    0
    1
    2
    
    In [238]: for k in x1:
       .....:     print k
       .....:
    
    In [239]:
    

    在 C# 中:

    class Program
    {
        static IEnumerable<int> Func1()
        {
            for (int i = 0; i < 3; i++)
                yield return i;
        }
    
        static void Main(string[] args)
        {
            var x1 = Func1();
            foreach (int k in x1) 
                Console.WriteLine(k);
    
            foreach (int k in x1)
                Console.WriteLine(k);
        }
    }
    

    这给了你:

    0
    1
    2
    0
    1
    2
    

    【讨论】:

      【解决方案3】:

      除了其他答案之外,需要注意的一个重要区别是 C# 中的 yield 不能用作表达式,只能用作语句。

      yield 表达式在 Python 中的用法示例(示例粘贴自 here):

      def echo(value=None):
        print "Execution starts when 'next()' is called for the first time."
        try:
          while True:
             try:
               value = (yield value)
             except GeneratorExit:
               # never catch GeneratorExit
               raise
             except Exception, e:
               value = e
           finally:
             print "Don't forget to clean up when 'close()' is called."
      
      generator = echo(1)
      print generator.next()
      # Execution starts when 'next()' is called for the first time.
      # prints 1
      
      print generator.next()
      # prints None
      
      print generator.send(2)
      # prints 2
      
      generator.throw(TypeError, "spam")
      # throws TypeError('spam',)
      
      generator.close()
      # prints "Don't forget to clean up when 'close()' is called."
      

      【讨论】:

      • 但是从您的链接表达式使用仅对生成器有益,这在 C# 中似乎可以通过在生成的 IEnumerable&lt;T&gt; 上调用 GetEnumerator 来实现,您将从 yielding 方法返回。跨度>
      • @KennethK。我不会以任何方式反驳我的回答。该问题询问的是 yield 关键字的差异,而不是返回的生成器/迭代器对象的处理方式的差异
      • 我不反对,但您的论点是“C# 中没有 yield 表达式”可以解决,“那么我不能在 C# 中做同样的事情,我可以在Python”,但似乎并非如此。 C# 不能做表达式输出的事实并不意味着你不能实现相同的功能(除非我误解了 Python 功能,这当然是可能的,因为 Python 不是我的强项)。
      • 据我了解,即使您可以在结果上调用GetEnumerator,您也无法将值传递给生成器函数,这就是yield 表达式在 Python 版本中计算。 IEnumerator 接口上没有与 Python 的 send() 生成器方法的语义相匹配的方法。
      • 好的,我明白你现在在说什么了。
      猜你喜欢
      • 2018-09-25
      • 1970-01-01
      • 2011-08-28
      • 2015-05-18
      • 2016-06-01
      • 2014-11-11
      • 1970-01-01
      • 2016-09-08
      • 2018-01-19
      相关资源
      最近更新 更多