2009-03-09 11 views
34

¿Es posible usar los tipos LINQ y los métodos de extensión en IronPython?¿Puede usar los tipos de LINQ y los métodos de extensión en IronPython?

Si es así, ¿cómo? ¿Y también hay a menudo más pitonica para hacer lo mismo?

+0

Ólafur, por favor seleccione la respuesta de Steve Gilham para que las personas que naveguen a esta pregunta vean la información correcta y actualizada. En 50K, no creo que John Feminella se pierda el representante. –

Respuesta

41

IronPython 2.7 finalmente cierra esta brecha con el método clr.ImportExtensions que agrega los métodos de extensión de un espacio de nombres a los tipos de destino, p.

>& 'C:\Program Files\IronPython 2.7\ipy.exe' 
IronPython 2.7 (2.7.0.40) on .NET 4.0.30319.225 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import clr 
>>> clr.AddReference("System.Core") 
>>> from System.Collections.Generic import List 
>>> dir (List) 
['Add', 'AddRange', 'AsReadOnly', 'BinarySearch', 'Capacity', 'Clear', 'Contains', 'ConvertAll', 'CopyTo', 'Count', 'Enu 
merator', 'Equals', 'Exists', 'Find', 'FindAll', 'FindIndex', 'FindLast', 'FindLastIndex', 'ForEach', 'GetEnumerator', ' 
GetHashCode', 'GetRange', 'GetType', 'IndexOf', 'Insert', 'InsertRange', 'IsReadOnly', 'IsSynchronized', 'Item', 'LastIn 
dexOf', 'MemberwiseClone', 'ReferenceEquals', 'Remove', 'RemoveAll', 'RemoveAt', 'RemoveRange', 'Reverse', 'Sort', 'Sync 
Root', 'ToArray', 'ToString', 'TrimExcess', 'TrueForAll', '__add__', '__class__', '__contains__', '__delattr__', '__doc_ 
_', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce 
__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__'] 
>>> import System 
>>> clr.ImportExtensions(System.Linq) 
>>> dir (List) 
['Add', 'AddRange', 'Aggregate', 'All', 'Any', 'AsEnumerable', 'AsParallel', 'AsQueryable', 'AsReadOnly', 'Average', 'Bi 
narySearch', 'Capacity', 'Cast', 'Clear', 'Concat', 'Contains', 'ConvertAll', 'CopyTo', 'Count', 'DefaultIfEmpty', 'Dist 
inct', 'ElementAt', 'ElementAtOrDefault', 'Enumerator', 'Equals', 'Except', 'Exists', 'Find', 'FindAll', 'FindIndex', 'F 
indLast', 'FindLastIndex', 'First', 'FirstOrDefault', 'ForEach', 'GetEnumerator', 'GetHashCode', 'GetRange', 'GetType', 
'GroupBy', 'GroupJoin', 'IndexOf', 'Insert', 'InsertRange', 'Intersect', 'IsReadOnly', 'IsSynchronized', 'Item', 'Join', 
'Last', 'LastIndexOf', 'LastOrDefault', 'LongCount', 'Max', 'MemberwiseClone', 'Min', 'OfType', 'OrderBy', 'OrderByDesc 
ending', 'ReferenceEquals', 'Remove', 'RemoveAll', 'RemoveAt', 'RemoveRange', 'Reverse', 'Select', 'SelectMany', 'Sequen 
ceEqual', 'Single', 'SingleOrDefault', 'Skip', 'SkipWhile', 'Sort', 'Sum', 'SyncRoot', 'Take', 'TakeWhile', 'ToArray', ' 
ToDictionary', 'ToList', 'ToLookup', 'ToString', 'TrimExcess', 'TrueForAll', 'Union', 'Where', 'Zip', '__add__', '__clas 
s__', '__contains__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', 
'__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__' 
, '__str__', '__subclasshook__'] 
>>> 

el que lo pone en línea con el método de IronRuby 1.1 using_clr_extensions.

23

Algunas de las cosas que haría con LINQ se puede hacer con las listas por comprensión:

[myFunc(i) for i in numbers if i > 3] 

o puede utilizar un mapa, reducir y filtro:

map(myFunc, filter(lambda x: x > 3, numbers)) 

Pero son listas por comprensión mucho más "Pythonic" que usar las construcciones de programación funcional. Para reducir las cosas, considere usar "" .unirse a o suma. Y puede comprobar el valor de verdad de iterables enteras mediante el uso de cualquier y todo

Sólo recuerde estas traducciones:

Select -> map 
Where -> filter 
Aggregate -> reduce 

y usted estará bien en su camino!

+3

también, set() es un buen reemplazo para Distinct() – Phil

3

I described a C# wrapper class alrededor de los métodos de extensión LINQ para lograr una sintaxis similar a la sintaxis de "método de extensión encadenado" de C# en IronPython.

La idea es tener un tipo de clase de decorador alrededor de IEnumerable que simplemente llame a los métodos de extensión. Es probable que esta clase de contenedor se puede escribir igual de bien en IronPython, pero no estoy tan fluido en Python todavía :-)

public class ToLinq<T> : IEnumerable<T> 
{ 
    private readonly IEnumerable<T> _wrapped; 

    public ToLinq(IEnumerable<T> wrapped) 
    { 
     _wrapped = wrapped; 
    } 

    public ToLinq<T> Where(Func<T, bool> predicate) 
    { 
     return new ToLinq<T>(_wrapped.Where(predicate)); 
    } 


    // ... similar methods for other operators like Select, Count, Any, ... 

} 

Esto permite una sintaxis similar a la siguiente:

johns = ToLinq[Customer](customers)\ 
      .Where(lambda c: c.Name.StartsWith("John"))\ 
      .Select(lambda c: c.Name) 

exención de responsabilidad : esto es algo que intenté como ejercicio de aprendizaje, no lo he usado en un proyecto del mundo real.

11

En IronPython 2.7.1 tiene clr.ImportExtensions para este caso de uso.

import clr 
clr.AddReference("System.Core") 
import System 
clr.ImportExtensions(System.Linq) 

# will print 3 and 4 :) 
[2, 3, 4].Where(lambda x: x != 2).ToList().ForEach(System.Console.WriteLine) 

Un poco de historia: IronPython 2.7 introdujo inicialmente esta característica, pero no había an issue el que se detuvo de ser realmente utilizable.

Cuestiones relacionadas