Can you use LINQ types and extension methods in IronPython?

后端 未结 4 1936
迷失自我
迷失自我 2021-01-30 13:28

Is it possible to use the LINQ types and extension methods in IronPython?

If so how? And also is there often more pythonic to do the same thing?

相关标签:
4条回答
  • 2021-01-30 13:59

    In IronPython 2.7.1 you have clr.ImportExtensions for this use case.

    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)
    

    A little background: IronPython 2.7 initially introduced this feature, but there was an issue which stopped it from being really usable.

    0 讨论(0)
  • 2021-01-30 14:05

    I described a C# wrapper class around the LINQ extension methods to achieve a syntax similar to C#'s 'chained extension method' syntax in IronPython.

    The idea is to have a kind of decorator class around IEnumerable that simply calls the extension methods. Probably this wrapper class can be written just as well in IronPython, but I'm not as fluent in python yet :-)

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

    This allows for a syntax similar to this:

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

    Disclaimer: this is something I tried as a learning excercise, I haven't used this in a real-world project.

    0 讨论(0)
  • 2021-01-30 14:15

    IronPython 2.7 finally bridges this gap with the clr.ImportExtensions method which adds the extension methods from a namespace to the target types 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__']
    >>>
    

    which brings it into line with IronRuby 1.1's using_clr_extensions method.

    0 讨论(0)
  • 2021-01-30 14:18

    Some of the things you'd do with LINQ can be done with list comprehensions:

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

    Or you can use map, reduce, and filter:

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

    But list comprehensions are much more "Pythonic" than using the functional programming constructs. For reducing things, consider using "".join or sum. And you can check the truth value of entire iterables by using any and all

    Just remember these translations:

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

    And you'll be well on your way!

    0 讨论(0)
提交回复
热议问题