【问题标题】:How to tell when a function in another class has been called如何判断何时调用了另一个类中的函数
【发布时间】:2010-10-28 13:51:20
【问题描述】:

我有两个 Python 类,分别称为“C1”和“C2”。 C1 内部是一个名为“F1”的函数,C2 内部是一个名为“F2”的函数。有没有办法在每次运行 F1 时执行 F2 而无需从 F1 内直接调用 F2?是否有其他机制可以知道何时调用了另一个类中的函数?

我欢迎任何建议,但想知道一些无需在 C1 中创建 C2 实例即可实现此目的的方法。

【问题讨论】:

  • +1 为好的描述,新用户。
  • 你想达到什么目的?直接调用有什么问题。似乎您想要函数上的 on call 事件之类的东西。这有点多余,您可以在函数本身中编写代码。
  • “在 C1 中创建 C2 的实例”?你这是什么意思?你能举例说明你在说什么吗?在 Python 中,一切都是引用,所以这个实例“在”另一个实例“内部”并没有多大意义。你在担心什么?

标签: python class


【解决方案1】:

您可以编写一个小助手装饰器来为您调用。优点是通过查看代码很容易判断谁将调用什么。您可以根据需要添加任意数量的函数调用。就像注册一个回调函数一样:

from functools import wraps

def oncall(call):
    def helper(fun):
        @wraps(fun)
        def wrapper(*args, **kwargs):
            result = fun(*args, **kwargs)
            call()
            return result
        return wrapper
    return helper

class c1:
   @classmethod
   def f1(cls):
      print 'f1'

class c2:
   @classmethod
   @oncall(c1.f1)
   def f2(cls):
      print 'f2'

>>> c2.f2()
f2
f1
>>> c1.f1()
f1

【讨论】:

    【解决方案2】:

    从 Python 2.2 开始,您可以使用函数和方法装饰器进行面向方面的编程:

    @decorator(decorator_args)
    def functionToBeDecorated(function_args) :
        pass
    

    【讨论】:

      【解决方案3】:

      我相信您正在尝试做的事情将适合Aspect Oriented Programming 的领域。但是我从未使用过这种方法,甚至不知道它是否可以/已经在 Python 中实现。

      编辑 我刚刚查看了我提供的链接,发现提到了8 Python implementations。所以已经为你完成了艰苦的工作:-)

      【讨论】:

        【解决方案4】:

        这实际上取决于您为什么不想直接从 F1 中调用 F2。您总是可以创建一个封装 C1 和 C2 的第三个类 (C3)。当调用 F3 时,它将同时调用 F1 和 F2。这被称为中介者模式 - http://en.wikipedia.org/wiki/Mediator_pattern

        【讨论】:

          【解决方案5】:

          不知道你想要达到什么目标,我建议你看看 pydispatcher。 它允许您实现观察者模式

          基本上,您向调度程序注册 F2,以便在发出特定“信号”时调用它。您的 F1 会“发出一个信号”,上面写着“我已被叫到”。然后调度程序调用 F2(或任何数量的已向该特定信号注册自身的函数)。 它实际上比听起来简单,易于使用,并且可以解耦您的代码(F1 不需要了解 F2)。

          (啊。。我是新用户,不允许包含超链接,但 pydispatcher 很容易用谷歌搜索)

          【讨论】:

            【解决方案6】:

            您可以使用 __getattr__ 捕获对 F1 的所有访问。这将允许您进行额外的处理或返回您自己的函数来代替 F1

            class C1:
              def __getattr__(self,name):
                if name == 'F1': C2.F2()
                return self[name]
            

            我应该警告你,即使 F1 只是被访问(而不是运行),它也会调用 C2.F2。 F1 可能只是出于其他目的而被访问,例如 f = myC1.F1 ,这种情况很少见,但并非不可能。要仅在调用 F1 时运行 F2,您需要扩展此示例以将 F2 与返回的函数对象结合起来。换句话说:

            def F1F2():
               self.F1()
               C2.F2()
            return F1F2
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-10-08
              • 1970-01-01
              • 2018-03-29
              • 1970-01-01
              • 1970-01-01
              • 2015-07-18
              • 2017-12-19
              • 2011-05-03
              相关资源
              最近更新 更多