Pergunta

É possível usar os tipos de LINQ e os métodos de extensão em IronPython?

Se sim, como? E também há muitas vezes mais Python para fazer a mesma coisa?

Foi útil?

Solução

IronPython 2,7 finalmente preenche esta lacuna com o método clr.ImportExtensions que adiciona os métodos de extensão a partir de um espaço de nomes para os tipos de destino e.g.

>& '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 traz-lo em linha com o método using_clr_extensions IronRuby 1.1 do.

Outras dicas

Algumas das coisas que você faria com o LINQ pode ser feito com compreensões lista:

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

Ou você pode usar o mapa, reduzir e filtro:

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

Mas compreensões lista são muito mais "Pythonic" do que usando as construções de programação funcional. Para reduzir as coisas, considere o uso de "". Juntar-se ou sum . E você pode verificar o valor de verdade de iterables inteiras usando qualquer e todas

Basta lembrar estas traduções:

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

E você será bem no seu caminho!

Na IronPython 2.7.1 você tiver 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)

Um pouco de fundo: IronPython 2.7 inicialmente introduzido este recurso, mas não havia an que parou de ser realmente utilizável.

I descreveu um C # classe wrapper em torno dos métodos de extensão LINQ para alcançar uma sintaxe semelhante ao C # 's 'encadeada método de extensão' sintaxe no IronPython.

A idéia é ter uma espécie de classe decorador torno IEnumerable que simplesmente chama os métodos de extensão. Provavelmente esta classe de mensagens publicitárias pode ser escrito tão bem em IronPython, mas eu não sou tão fluente em python ainda: -)

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, ...

}

Isto permite uma sintaxe semelhante a esta:

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

Disclaimer: este é algo que eu tentei como um exercício de aprendizagem, eu não usei isso em um projeto do mundo real.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top