在python中显式传递函数

2024-09-28 05:27:47 发布

您现在位置:Python中文网/ 问答频道 /正文

出于好奇,更可取的做法是显式地将函数传递给其他函数,或者让函数从内部调用函数。这是显式比隐式好吗?你知道吗

例如(以下只是为了说明我的意思)

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])

Tags: 函数mapreturniffoodefbarpartial
3条回答

一般来说,是的,但总是要视情况而定。你在这里说明的是dependency injection。一般来说,这是一个好主意,因为它允许从给定函数的逻辑分离可变性。例如,这意味着您将非常容易地测试这些代码。你知道吗

# To test the process performed in bar(), we can "inject" a function
# which simply returns its argument
def dummy(x):
    return x

def bar(fn,xs,ys):
    return fn(sum(map(operator.mul,xs,ys)))

>>> assert bar(dummy, [1,2,3], [4,5,6]) == 32

这在很大程度上取决于上下文。你知道吗

基本上,如果函数是bar的参数,那么调用者就有责任知道如何实现该函数。bar不必在意。但是因此,bar的文档必须描述它需要什么样的函数。你知道吗

通常这是非常合适的。显而易见的例子是map内置函数。map实现将函数应用于列表中的每个项并返回结果列表的逻辑。map本身既不知道也不关心项是什么,也不关心函数对它们做了什么。map的文档必须描述它需要一个参数的函数,map的每个调用方必须知道如何实现或找到合适的函数。但是这种安排很好;它允许您传递一个自定义对象的列表,以及一个专门对这些对象进行操作的函数,并且map可以离开并执行它的通用操作。你知道吗

但这种安排往往是不恰当的。函数为高级操作命名并隐藏内部实现细节,因此可以将操作视为一个单元。允许它的部分操作作为函数参数从外部传入,暴露了它以使用该函数接口的方式工作。你知道吗

一个更具体的(尽管有些做作)例子可能会有所帮助。假设我已经实现了表示PersonJob的数据类型,我正在编写一个函数name_and_title,用于将某人的全名和职务格式化为字符串,用于将客户机代码插入电子邮件签名或信头或其他内容。很明显这需要PersonJob。它可能需要一个函数参数来让调用者决定如何格式化人名:类似于lambda firstname, lastname: lastname + ', ' + firstname。但这样做是为了暴露我用一个单独的名字和姓氏来代表人们的名字。如果我想更改为支持中间名,那么name_and_title将不能包含中间名,或者我必须更改它接受的函数的类型。当我意识到有些人有4个或4个以上的名字并决定更改为存储一个名字列表时,我肯定必须更改name_and_title接受的函数的类型。你知道吗

所以对于你的bar例子,我们不能说哪个更好,因为这是一个没有意义的抽象例子。这取决于对partialfun的调用是否是bar应该做的事情的实现细节,或者对partialfun的调用是否是调用方知道的事情(并且可能想做其他事情)。如果它是“bar的一部分,那么它不应该是一个参数。如果它是调用者的“一部分”,那么它应该是一个参数。你知道吗

值得注意的是,bar可能有大量的函数参数。您可以调用summapoperator.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来执行函数。你知道吗

因此,真的没有一个明确的答案,无论这种或那种方式,适用于所有的时间。这取决于你写的特定代码。你知道吗

在这种情况下,函数和其他函数之间并没有什么区别。如果某个参数在函数的不同调用中可能有所不同,则可以将其作为参数传递。如果您正在调用的函数(bar在您的示例中)总是调用相同的其他函数,那么没有理由将其作为参数传递。如果需要参数化它,以便可以使用许多不同的函数(即bar可能需要调用partialfun之外的许多函数,并且需要知道要调用哪个函数),那么需要将它作为参数传递。你知道吗

相关问题 更多 >

    热门问题