代码之家  ›  专栏  ›  技术社区  ›  Ben2209

将methodcaller和attrgetter与排序

  •  2
  • Ben2209  · 技术社区  · 6 年前

    我想获得PosixPath对象的列表,并根据相应的文件大小对其进行排序。我正在尝试使用排序函数来解决这个问题。我要用于排序的键是 object.stat().st_size ,其中object是PosixPath对象, stat() 返回 os.stat_result 对象,以及 st_size 是与PosixPath对象相对应的文件的大小。我知道如何使用 operator.methodcaller operator.attrgetter ,但我不知道如何使用 methodcaller

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

    from operator import attrgetter, methodcaller
    from pathlib import Path
    
    sorted(Path('my_directory').glob('*.extension'), key=methodcaller('stat').st_size)
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Thierry Lathuille    6 年前

    它们不应该结合在一起。您应该使用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()))
    

    如果你真的想 methodcaller attrgetter ,您可以执行以下操作:

    sorted(Path('.').glob('*.py'), key=lambda p: attrgetter('st_size')(methodcaller('stat')(p)))
    
        2
  •  1
  •   jpp    6 年前

    Function composition 在Python中不是本机的。

    应用逻辑的一种可读方法是使用直接而非功能路线:

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

    但是,有些第三方库确实提供此功能,例如 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