【问题标题】:Combining methodcaller and attrgetter with sorted将 methodcaller 和 attrgetter 与 sorted 相结合
【发布时间】:2018-05-06 15:32:04
【问题描述】:

我想获取 PosixPath 对象的列表,并根据相应的文件大小对其进行排序。我正在尝试使用排序功能来做到这一点。我要用于排序的键是object.stat().st_size,其中object 是一个PosixPath 对象,stat() 返回一个os.stat_result 对象,st_size 是PosixPath 对象对应的文件大小。我知道如何使用operator.methodcalleroperator.attrgetter 根据对象方法或对象属性进行排序,但我不知道如何使用methodcaller 返回的对象的属性。

我尝试了以下和一些变体,但它不起作用:

from operator import attrgetter, methodcaller
from pathlib import Path

sorted(Path('my_directory').glob('*.extension'), key=methodcaller('stat').st_size)

【问题讨论】:

    标签: python python-3.x sorting functional-programming nested


    【解决方案1】:

    它们不是用来组合的。您应该使用 lambda 作为键:

    from pathlib import Path
    sorted(Path('.').glob('*.py'), key=lambda p: p.stat().st_size)
    

    或者,如果您想动态更改排序字段:

    key_field = 'st_mtime'
    sorted(Path('.').glob('*.py'), 
           key=lambda p: attrgetter(key_field)(p.stat()))
    

    而且,如果你真的想使用methodcallerattrgetter,你可以这样做:

    sorted(Path('.').glob('*.py'), key=lambda p: attrgetter('st_size')(methodcaller('stat')(p)))
    

    【讨论】:

      【解决方案2】:

      Function composition 不是 Python 原生的。

      应用您的逻辑的一种可读方式是使用直接路径而不是函数路径:

      res = sorted(Path('.').glob('*.py'), key=lambda p: p.stat().st_size)
      

      不过,也有 3rd 方库提供此功能,例如 toolz

      from toolz import compose
      from operator import attrgetter, methodcaller
      
      get_size = compose(attrgetter('st_size'), methodcaller('stat'))
      
      res = sorted(Path('.').glob('*.py'), key=get_size)
      

      在我看来,如果你想要一个函数式的解决方案,你应该使用或编写一个复合高阶函数,例如上面的,以确保你的代码可读。

      相关:Nested lambda statements when sorting lists

      【讨论】:

        猜你喜欢
        • 2015-12-21
        • 2021-08-02
        • 2020-05-23
        • 1970-01-01
        • 1970-01-01
        • 2019-12-02
        • 2012-05-19
        • 2020-05-04
        • 1970-01-01
        相关资源
        最近更新 更多