出于好奇,更可取的做法是显式地将函数传递给其他函数,或者让函数从内部调用函数。这是显式比隐式好吗?你知道吗
例如(以下只是为了说明我的意思)
def foo(x,y):
return 1 if x > y else 0
partialfun = functools.partial(foo, 1)
def bar(xs,ys):
return partialfun(sum(map(operator.mul,xs,ys)))
>>> bar([1,2,3], [4,5,6])
--或--
def foo(x,y):
return 1 if x > y else 0
partialfun = functools.partial(foo, 1)
def bar(fn,xs,ys):
return fn(sum(map(operator.mul,xs,ys)))
>>> bar(partialfun, [1,2,3], [4,5,6])
一般来说,是的,但总是要视情况而定。你在这里说明的是dependency injection。一般来说,这是一个好主意,因为它允许从给定函数的逻辑分离可变性。例如,这意味着您将非常容易地测试这些代码。你知道吗
这在很大程度上取决于上下文。你知道吗
基本上,如果函数是
bar
的参数,那么调用者就有责任知道如何实现该函数。bar
不必在意。但是因此,bar
的文档必须描述它需要什么样的函数。你知道吗通常这是非常合适的。显而易见的例子是
map
内置函数。map
实现将函数应用于列表中的每个项并返回结果列表的逻辑。map
本身既不知道也不关心项是什么,也不关心函数对它们做了什么。map
的文档必须描述它需要一个参数的函数,map
的每个调用方必须知道如何实现或找到合适的函数。但是这种安排很好;它允许您传递一个自定义对象的列表,以及一个专门对这些对象进行操作的函数,并且map
可以离开并执行它的通用操作。你知道吗但这种安排往往是不恰当的。函数为高级操作命名并隐藏内部实现细节,因此可以将操作视为一个单元。允许它的部分操作作为函数参数从外部传入,暴露了它以使用该函数接口的方式工作。你知道吗
一个更具体的(尽管有些做作)例子可能会有所帮助。假设我已经实现了表示
Person
和Job
的数据类型,我正在编写一个函数name_and_title
,用于将某人的全名和职务格式化为字符串,用于将客户机代码插入电子邮件签名或信头或其他内容。很明显这需要Person
和Job
。它可能需要一个函数参数来让调用者决定如何格式化人名:类似于lambda firstname, lastname: lastname + ', ' + firstname
。但这样做是为了暴露我用一个单独的名字和姓氏来代表人们的名字。如果我想更改为支持中间名,那么name_and_title
将不能包含中间名,或者我必须更改它接受的函数的类型。当我意识到有些人有4个或4个以上的名字并决定更改为存储一个名字列表时,我肯定必须更改name_and_title
接受的函数的类型。你知道吗所以对于你的
bar
例子,我们不能说哪个更好,因为这是一个没有意义的抽象例子。这取决于对partialfun
的调用是否是bar
应该做的事情的实现细节,或者对partialfun
的调用是否是调用方知道的事情(并且可能想做其他事情)。如果它是“bar
的一部分,那么它不应该是一个参数。如果它是调用者的“一部分”,那么它应该是一个参数。你知道吗值得注意的是,
bar
可能有大量的函数参数。您可以调用sum
、map
和operator.mul
,这些都可以参数化以使bar
更灵活:对
g
的输出调用h
的方式也可以抽象:我们可以一直这样下去,直到
bar
什么都不做,一切都由传入的函数控制,调用者也可以直接做他们想做的事情,而不是编写100个函数来做,然后将它们传递给bar
来执行函数。你知道吗因此,真的没有一个明确的答案,无论这种或那种方式,适用于所有的时间。这取决于你写的特定代码。你知道吗
在这种情况下,函数和其他函数之间并没有什么区别。如果某个参数在函数的不同调用中可能有所不同,则可以将其作为参数传递。如果您正在调用的函数(
bar
在您的示例中)总是调用相同的其他函数,那么没有理由将其作为参数传递。如果需要参数化它,以便可以使用许多不同的函数(即bar
可能需要调用partialfun
之外的许多函数,并且需要知道要调用哪个函数),那么需要将它作为参数传递。你知道吗相关问题 更多 >
编程相关推荐