Python:向可调用函数传递额外参数

5

我有以下的Python代码:

import networkx as nx 

def cost(i, j, d, value1, value2):
    # some operation involving all these values
    return cost


# graph is a networkx graph
# src, dst are integers
# cost is a callable that is passed 3 values automatically i.e. src, dst and d 
# d is a dictionary of edge weights
path = nx.dijkstra_path(graph, src, dst, weight=cost)

现在我想将两个值value1value2传递给cost函数。 networkx文档表示weight可以是一个接受3个参数的可调用函数。但我需要value1value2进行计算。如何做到这一点? 编辑 使用functools的解决方案很好。但是,我的函数在一个类中,如下所示:
import networkx as nx 
import functools
class Myclass:
    def cost(self, i, j, d, value2):
        # some operation involving all these values
        # also need self


    # graph is a networkx graph
    # src, dst are integers
    # cost is a callable that is passed 3 values automatically i.e. src, dst and d 
    # d is a dictionary of edge weights
    # path = nx.dijkstra_path(graph, src, dst, cost)
    cost_partial = functools.partial(cost, self=self, value2=5)
    path = nx.dijkstra_path(graph, src, dst, cost_partial)

使用这种方法,nx.dijkstra_path一定会将src分配给self。因此解释器会抱怨self被分配了多个值。 我需要self来计算成本。


这些值从哪里来?如果它们是已知的,并且对于所有函数调用都不会改变,为什么不将它们作为全局变量呢? - AntiMatterDynamite
1
@AntiMatterDynamite 因为全局变量往往会导致代码混乱,而且极少是正确的解决方案,所以它们并不受欢迎。 - DeepSpace
1
@AntiMatterDynamite 我真的不会试图“说服”你为什么全局变量是一个坏主意。 - DeepSpace
1
@AntiMatterDynamite 不是为了提供错误的建议... - DeepSpace
1
@DeepSpace 我并不是在建议使用全局变量,我只是在询问函数被重复调用时值是否会发生改变,这可能会使得此处给出的一些答案失效... - AntiMatterDynamite
显示剩余8条评论
2个回答

14

你只需要编写一个包装 cost 的函数。一种快速的方法是使用 functools.partial

import functools

def cost(i, j, d, value1, value2):
    'Example function'
    return i, j, d, value1, value2

# This makes a new function which takes all parameters of `cost` except those 
# you've already passed. Here I'm going to set value1 and value2 to 1 and 2 
# respectively.
cost_partial = functools.partial(cost, value1=1, value2=2)

# A new function that only accepts the 3 args i, j, d
cost_partial('i', 'j', 'd')  # --> ('i', 'j', 'd', 1, 2)

# use as
path = nx.dijkstra_path(graph, src, dst, weight=cost_partial)

只是确认这个解决方案在我的类似情况下非常有效,我尝试将第四个参数传递给networkx中的filter_edge可调用函数,该函数位于networkx.classes.function.subgraph_view(G, filter_node, filter_edge)函数中。非常感谢! - whydoesntwork

4
这在很大程度上取决于value1value2的含义。我建议添加一个由networkx调用的包装器:
def cost_wrapper(i, j, d):
    value1 = 0  # set values as needed
    value2 = 1
    return cost(i, j, d, value1, value2)

并将其提供给networkx:

path = nx.dijkstra_path(graph, src, dst, weight=cost_wrapper)

或者将它们作为全局变量而不是参数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接