【发布时间】:2011-07-02 18:26:41
【问题描述】:
在 Python 中,是否被认为是更好的样式:
- 根据更一般的、可能是内部使用的功能明确定义有用的功能;或者,
- 使用偏函数应用显式描述函数柯里化?
我将通过一个人为的例子来解释我的问题。
假设有人编写了一个函数 _sort_by_scoring,它接受两个参数:一个评分函数和一个项目列表。它根据每个项目在原始列表中的位置返回按分数排序的原始列表的副本。还提供了两个示例评分函数。
def _sort_by_score(scoring, items_list):
unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)]
sorted_list = [item for score, item in sorted(unsorted_scored_list)]
return sorted_list
def _identity_scoring(items_list_size, item_position):
return item_position
def _reversed_scoring(items_list_size, item_position):
return items_list_size - item_position
永远不会直接调用函数_sort_by_score;相反,它由其他单参数函数调用,这些函数将评分函数及其唯一参数(项目列表)传递给 _sort_by_scoring 并返回结果。
# Explicit function definition style
def identity_ordering(items_list):
return _sort_by_score(_identity_scoring, items_list)
def reversed_ordering(items_list):
return _sort_by_score(_reversed_scoring, items_list)
显然,这个意图用函数柯里化来表达更好。
# Curried function definition style
import functools
identity_ordering = functools.partial(_sort_by_score, _identity_scoring)
reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring)
用法(在任何一种情况下):
>>> foo = [1, 2, 3, 4, 5]
>>> identity_ordering(foo)
[1, 2, 3, 4, 5]
>>> reversed_ordering(foo)
[5, 4, 3, 2, 1]
显式函数定义风格的明显优势:
- 可以在更通用的函数之前定义有用的函数,而不会引发 NameErrors;
- 可以在函数定义体中定义辅助函数(例如评分函数);
- 可能更容易调试;
- 代码看起来不错,因为“显式优于隐式”。
柯里化函数定义风格的明显优势:
- 以惯用方式表达函数式编程的意图;
- 代码简洁美观。
对于定义“有用”的功能,两种风格中的哪一种更受欢迎?还有其他更惯用/Pythonic/等的样式吗?
【问题讨论】:
-
一个旁注,柯里化和部分应用是两个不同的东西。柯里化意味着将函数转换为一次处理一个参数。因此,当您应用第一个参数时,您会得到一个函数,然后您可以应用第二个参数。部分应用只是为函数调用修复了一些参数
标签: python functional-programming currying partial-application