¿Se pueden usar los tipos LINQ y los métodos de extensión en IronPython?

StackOverflow https://stackoverflow.com/questions/628482

  •  06-07-2019
  •  | 
  •  

Pregunta

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

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

¿Fue útil?

Solución

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

>& '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__']
>>>

que lo alinea con el método de IronRuby 1.1 usando_clr_extensions .

Otros consejos

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

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

O puede usar el mapa, reducir y filtrar:

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

Pero las comprensiones de listas son mucho más "Pythonic" que usar las construcciones de programación funcional. Para reducir las cosas, considere usar " " .join o sum . Y puede verificar el valor de verdad de iterables enteros utilizando any y all

Solo recuerda estas traducciones:

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

¡Y estarás bien encaminado!

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 función, pero había un problema que impedía que fuera realmente utilizable.

I describió una clase de envoltura de C # alrededor de los métodos de extensión de LINQ para lograr una sintaxis similar a la sintaxis de 'método de extensión encadenada' de C # en IronPython.

La idea es tener una clase de decorador alrededor de IEnumerable que simplemente llame a los métodos de extensión. Probablemente esta clase de contenedor se pueda escribir igual de bien en IronPython, pero todavía no soy tan fluido en python :-)

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 esta:

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

Descargo de responsabilidad: esto es algo que probé como ejercicio de aprendizaje, no lo he usado en un proyecto del mundo real.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top