这在很大程度上取决于上下文。
基本上,如果函数是 的参数bar,那么调用者有责任知道如何实现该函数。bar不必在意。但因此,bar的文档必须描述它需要什么样的功能。
通常这是非常合适的。最明显的例子是map内置函数。map实现将函数应用于列表中的每个项目并返回结果列表的逻辑。map它本身既不知道也不关心这些项目是什么,或者函数对它们做了什么。map的文档必须描述它需要一个参数的函数,并且每个调用者map都必须知道如何实现或找到合适的函数。但是这种安排很棒;它允许您传递自定义对象的列表,以及专门对这些对象进行操作的函数,并且map可以离开并执行其通用操作。
但这种安排往往是不合适的。函数为高级操作命名并隐藏内部实现细节,因此您可以将操作视为一个单元。允许其部分操作作为函数参数从外部传入,这表明它以使用该函数接口的方式工作。
一个更具体(虽然有些人为)的例子可能会有所帮助。假设我已经实现了表示Personand的数据类型Job,并且我正在编写一个函数name_and_title,用于将某人的全名和职位格式化为字符串,以便客户端代码插入电子邮件签名或信头或其他任何内容。这显然需要一个Personand Job。它可能需要一个函数参数来让调用者决定如何格式化人名:类似于lambda firstname, lastname: lastname + ', ' + firstname. 但这样做是为了暴露我用单独的名字和姓氏来代表人们的名字。如果我想更改为支持中间名,那么要么name_and_title将无法包含中间名,或者我必须更改它接受的函数的类型。当我意识到有些人有 4 个或更多名称并决定更改为存储名称列表时,我肯定必须更改函数name_and_title接受的类型。
所以对于你的bar例子,我们不能说哪个更好,因为它是一个没有意义的抽象例子。这取决于调用是否是应该做partialfun的任何事情的实现细节,或者调用是否是调用者知道的事情(并且可能想要做其他事情)。如果它是 "part of" ,那么它不应该是一个参数。如果它是调用者的“一部分”,那么它应该是一个参数。barpartialfunbar
值得注意的是,它bar可能有大量的函数参数。您调用sum、map和operator.mul,它们都可以被参数化以使其bar更灵活:
def bar(fn, xs,ys, g, h, i):
return fn(g(h(i,xs,ys))
也可以抽象g出调用输出的方式:h
def bar(fn, xs, ys, g, h, i, j):
return fn(j(g, h(i, xs, ys)))
而且我们可以一直继续下去,直到bar什么都不做,一切都由传入的函数控制,调用者还不如直接做他们想做的事情,而不是写100个函数来做并将它们传递bar给执行功能。
因此,实际上并没有一个始终适用的明确答案。这取决于您正在编写的特定代码。