Python的列表理解与.NET LINQ
以下简单的LINQ代码
string[] words = { "hello", "wonderful", "linq", "beautiful", "world" }; // Get only short words var shortWords = from word in words where word.Length <= 5 select word; // Print each word out shortWords.Dump(); 可以使用列表理解翻译成python如下。
 words = ["hello", "wonderful", "linq", "beautiful", "world"] shortWords = [x for x in words if len(x) <=5] print shortWords 
- LINQ只是实现列表理解的另一个想法吗?
- LINQ可以做什么样的例子,但列表理解是不能做的。
(警告:猛犸象的答案在前面,直到第一条水平线的部分是好的,我想是dr部分)
我不确定我是否有资格成为Python大师……但是我对Python中的迭代有一个很好的把握,所以让我们试试:)
首先:Afaik,LINQ查询是懒惰地执行的 – 如果是这种情况,生成器expression式是一个更接近Python的概念(无论哪种方式,列表,字典和集合的概念只是在列表/字典/集合构造函数中产生的expression式! )。
 另外,还有一个概念上的区别:LINQ正如名称所说,查询数据结构。  List- / dict- / set comprehensions是可能的应用(例如过滤和投影列表的项目)。 所以他们实际上不那么普遍(正如我们将会看到的,LINQ中内置的许多东西都不是内置的)。 同样,生成器expression式是一种用来形成一次性前向迭代器的方式(我喜欢把它看作是生成器函数的lambda,只有没有丑陋的长关键字)),而不是一种描述复杂查询的方法。 他们重叠,是的,但他们不完全相同。 如果你想在Python中使用LINQ的所有function,你将不得不编写一个完整的生成器。 或者结合内置和itertools的众多强大的发生器。 
现在,Python对应的LINQfunctionJon Skeet命名为:
 预测: (x.foo for ...) 
 过滤: (... if x.bar > 5) 
- 联合(x联合y在x.foo等于y.bar)
 最接近的是((x_item, next(y_item for y_item in y if x_item.foo == y_item.bar)) for x_item in x) ,我想。 
请注意,这不会遍历整个y每个x_item,它只会得到第一个匹配。
- 组连接(x在x.foo上连接y等于y.bar为g)
 这很难。  Python没有匿名types,尽pipe如果你不介意与__dict__混淆的话,它们是__dict__ : 
 class Anonymous(object): def __init__(self, **kwargs): self.__dict__ = kwargs 
 然后,我们可以做(Anonymous(x=x, y=y) for ...)来获得具有相应值的x和y成员的对象列表。 正确的事情通常是将结果提供给一个合适的类的构造函数,比如XY。 
- 分组(由x.bar组成的x.foo)
现在它变得毛茸茸的…没有固定的方式,afaik。 但是如果我们需要的话,我们可以自己定义它:
 from collections import defaultdict def group_by(iterable, group_func): groups = defaultdict(list) for item in iterable: groups[group_func(item)].append(item) return groups 
例:
 >>> from operator import attrgetter >>> group_by((x.foo for x in ...), attrgetter('bar')) defaultdict(<class 'list'>, {some_value_of_bar: [x.foo of all x where x.bar == some_value_of_bar], some_other_value_of_bar: [...], ...}) 
尽pipe如此,这就要求我们分组的任何东西都是可排除的。 这是可以避免的,如果有公众需求,我会做出一个刺。 但现在,我正在懒惰:)
 我们也可以通过在结果上调用.values()来返回一个没有我们分组的值的迭代组(当然,我们可以提供这个 list来获得我们可以索引和迭代几次的东西)。 但谁知道我们是否需要团体价值? 
- sorting(orderby x.foo升序,y.bar降序)
 sorting需要特殊的语法? 内置的sorted工作的iterables也: sorted(x % 2 for x in range(10)) sorted(x for x in xs, key=attrgetter('foo')) sorted(x % 2 for x in range(10))或sorted(x for x in xs, key=attrgetter('foo')) 。 按照默认的升序sorting,关键字参数reverse按降序排列。 
唉,通过多个属性进行sorting并不是那么容易,尤其是在混合升序和降序时。 嗯…配方的主题?
- 中间variables(让tmp = x.foo)
不,在理解或生成器expression式中是不可能的,正如名字所说,它们应该是expression式(通常只有一行或两行)。 但是,在发电机function中完全可能:
 (x * 2 for x in iterable) 
重写为具有中间variables的生成器:
 def doubles(iterable): for x in iterable: times2 = x * 2 yield times2 
 展平: (c for s in ("aa","bb") for c in s ) 
请注意,虽然LINQ to Objects处理委托,但是其他查询提供者(例如LINQ to SQL)可以处理描述查询的expression式树,而不是只呈现可执行的委托。 这允许将查询翻译成SQL(或其他查询语言) – 再一次,我不知道Python是否支持这种事情。 这是LINQ的重要组成部分。
  Python绝对没有这样的事情。 列表expression式一对一地在一个(可能嵌套的)for循环中累积一个普通列表,生成器expression式与一个生成器一一对应。 给定parser和ast模块, 理论上可以编写一个库来将理解转换为例如SQL查询。 但是没有人关心。 
那么,你需要区分一些不同的东西:
- LINQ标准查询运算符
- 在C#中的LINQ查询expression式
- VB中的LINQ查询expression式
C#不像VB那样支持查询expression式,但是它支持的是:
-  投影( select x.foo)
-  过滤( where x.bar > 5)
-   x join y on x.foo equals y.bar(x join y on x.foo equals y.bar)
-  组连接( x join y on x.foo equals y.bar into g)
-  分组( group x.foo by x.bar)
-  sorting( orderby x.foo ascending, y.bar descending)
-  中间variables( let tmp = x.foo)
-  展平( from x in y from z in x)
我不知道有多less人直接支持Python的列表parsing。
请注意,虽然LINQ to Objects处理委托,但是其他查询提供者(例如LINQ to SQL)可以处理描述查询的expression式树 ,而不是只呈现可执行的委托。 这允许将查询翻译成SQL(或其他查询语言) – 再一次,我不知道Python是否支持这种事情。 这是LINQ的重要组成部分。
通过使用asq Python包,您可以轻松地完成大部分Python中的工作,您可以在C#中使用LINQ for …对象进行操作。 使用asq,你的Python例子变成:
 from asq.initiators import query words = ["hello", "wonderful", "linq", "beautiful", "world"] shortWords = query(words).where(lambda x: len(x) <= 5) 
我不是Python大师,但我会说,Python实际上支持所有这些,因为你可以嵌套列表parsing,并包括所有你想要的lambdaexpression式。 (如果列表理解过于复杂,往往难以理解,但是,不包括“特定语法”来完成这一切。
 大多数function可以使用以下方式进行复制: – 列表parsing或生成器 –  lambda函数或内置函数(如filter()或map() )或itertools模块中的函数 
例如,如果您想复制以下行为:
-   预测 :这将是列表理解的左边部分…可以是单值,也可以是元组。 例如: [ (k,v) for k,v in my_dict.items() if k.startswith("abc"]。也可以使用map()
-   过滤 :这将是在if之后的右侧expression式。 你也可以使用filter()
-   sorting :只需使用内置的sorted()
-   分组或汇总 :使用内buildmin(),max()或itertools.groupby()
关于join或扁平化 ,我认为你将不得不“手动”…
(总是有好的Python达到快速参考 )