【问题标题】:Can you use LINQ types and extension methods in IronPython?你能在 IronPython 中使用 LINQ 类型和扩展方法吗?
【发布时间】:2022-01-06 23:15:49
【问题描述】:

是否可以在 IronPython 中使用 LINQ 类型和扩展方法?

如果有怎么办?而且经常有更多的pythonic来做同样的事情吗?

【问题讨论】:

    标签: linq ironpython


    【解决方案1】:

    IronPython 2.7 最终通过 clr.ImportExtensions 方法弥补了这一差距,该方法将扩展方法从命名空间添加到目标类型,例如

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

    这使其符合 IronRuby 1.1 的 using_clr_extensions 方法。

    【讨论】:

      【解决方案2】:

      使用 LINQ 可以完成的一些事情可以通过列表推导来完成:

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

      或者你可以使用mapreducefilter

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

      但是列表推导比使用函数式编程结构更“Pythonic”。为了减少事情,考虑使用"".joinsum。您可以使用anyall 来检查整个迭代的真值。

      只要记住这些翻译:

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

      你会一路走好!

      【讨论】:

        【解决方案3】:

        IronPython 2.7.1 中,您有 clr.ImportExtensions 用于此用例。

        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)
        

        一点背景知识:IronPython 2.7 最初介绍了这个功能,但有 an issue 阻止了它真正可用。

        【讨论】:

          【解决方案4】:

          described a C# wrapper class 围绕 LINQ 扩展方法实现了类似于 IronPython 中 C# 的“链式扩展方法”语法的语法。

          这个想法是在IEnumerable 周围有一种装饰器类,它简单地调用扩展方法。可能这个包装类也可以用 IronPython 编写,但我对 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, ...
          }
          

          这允许类似这样的语法:

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

          免责声明:这是我作为学习练习尝试的。我没有在实际项目中使用过它。

          【讨论】:

            猜你喜欢
            • 2010-09-19
            • 1970-01-01
            • 1970-01-01
            • 2013-04-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多