如何将类方法作为参数传递给该类外部的函数?

Posted

技术标签:

【中文标题】如何将类方法作为参数传递给该类外部的函数?【英文标题】:How to pass a class method as an argument to a function external to that class? 【发布时间】:2015-10-04 10:30:13 【问题描述】:

这对我来说是这样的:

class SomeName:
  def __init__(self):
    self.value = "something"
  def some_method(self):
    print self.value

def external_func(instance, method):
  method(instance)

external_func(SomeName(), SomeName.some_method)

这似乎工作正常。这是正确的做法吗?

【问题讨论】:

你可以传递SomeName().some_method然后调用method(),它也不是一个真正的类方法,因为你用实例调用它 @PadraicCunningham 我认为 OP 可能只是意味着“类的方法”,而不是类方法。 但是它需要能够使用稍后计算的数据来调用它。有一些函数 foo(),除了用于(例如)一些取决于地区或其他东西的税收计算的方法(我的目标是防止代码重复)之外,所有步骤都是相同的。 @zehelvion,不确定有什么区别,您可以调用该方法并传递您喜欢的任何内容,如果您觉得可能有问题,可以为您的问题添加更多上下文 【参考方案1】:

您的代码是“技术上正确的”(它可以满足您的要求)但是 - 至少在您的示例中 - 非常没用:

def external_func(instance, method):
  method(instance)

external_func(SomeName(), SomeName.some_method)

等同于:

def external_func(method):
  method()

external_func(SomeName().some_method)

与哪个FWIW相同:

SomeName().some_method()

但我想你已经明白了。

现在您可能有理由尝试将方法和实例都传递给external_func(),或者可能有更好的方法来解决您的实际问题...

【讨论】:

哦,在实际情况下,该函数需要使用类实例中的一种特定方法来构造和执行一些冗长的计算。【参考方案2】:

取决于你在做什么。因为函数也是 Python 中的对象,所以可以这样做。

但这是一个好的解决方案吗?似乎您正在尝试处理一个可能可以通过更多面向对象的方法更好地解决的问题:

class A:
    def __init__(self):
        self.value = "class A"
    def some_method(self):
        print self.value

class B:
    def __init__(self):
        self.value = "class B"
    def some_method(self):
        print self.value

some_class = A()
some_class.some_method()

some_class = B()
some_class.some_method()

输出:

"class A"
"class B"

在我看来,这将是一种更好的方法(如果在您的情况下这是可能/合理的):您只需在您的班级上调用 some_method(),甚至可能不知道您正在处理的对象的确切类型(关于遗产)。类本身知道该做什么,并在其方法被调用时做出相应的反应。

当您使用您没有影响的外部库时,这当然不起作用。

【讨论】:

在我的例子中,类本身是相同的并且熟悉两种(或更多)行为,但情况发生了变化。想象一下,一个Dog 类可以bitebarkgrowl 取决于所有者的决定。我们需要将主人想要的行为传递给尚未出生的狗。狗分配/计算过程始终相同,但行为是一个参数。狗是根据提供的一些数据计算得出的。 当我们尝试根据现实世界的对象对类进行建模时,向未出生的狗请教bark 会有点奇怪,不是吗?有没有办法等到狗被创造出来再决定告诉它该做什么? 我开始认为这是对的。有一个模型(实例)和一个上下文,是模型需要表现的。想象一个人在正式的企业中,而同一个人在摇滚音乐会中。函数/脚本获取输入以生成人员实例和情况(适当的行为)。它用于确定具有指定行为的派生实例的结果。 @wolfdawn 评论晚了,但无论如何:你上面描述的看起来像是策略模式。【参考方案3】:

我当然不知道你到底在做什么,但在我看来你试图在一个函数内部做太多事情。简单地拆分external_func 的内容可能会更好地解决您的问题。

据我了解,这里的目标是您不提前知道对象/方法对是什么,并希望减少代码重复。

也许这样会更好:

def main():
    obj = SomeName()
    # do the setting up portion 
    complex_object = external_func_set_up(obj)
    # presumably at some point you have to designate the method to be used:
    method = get_method_name(obj) 
    # run the method:
    getattr(obj, method)()
    # finish up the external operation: 
    external_func_complete(***args***) 

我知道这是更多的代码,但我认为最终发生的事情要清楚得多,并且可能会迫使您更多地思考您的问题(并可能提出更好的解决方案)。

【讨论】:

【参考方案4】:

如果您的方法中没有使用实例数据,您可以传递 SomeName().some_method 或制作 some_metod staticmethodclassmethod

查看文档以了解有关staticmethodclassmethod 的更多信息:

https://docs.python.org/3/library/functions.html#staticmethod https://docs.python.org/3/library/functions.html#classmethod

【讨论】:

它不是一个静态方法,它有一个self 参数并且依赖于示例类的value 属性。因此,根据定义,它不是静态的。 你是对的,但正如我所见,value 是常量,因此可以将其定义为类属性,因此可以使用classmethod

以上是关于如何将类方法作为参数传递给该类外部的函数?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将类引用作为参数传递给 VB Net 中的函数吗?

Actionscript 3:将类作为参数传递

试图将类作为参数传递给不同的类构造函数,但出现“转换”错误

将类作为参数传递给方法,然后调用静态方法

将对象作为参数传递给函数

使用on()jQuery方法将'this'作为参数传递给事件处理程序