如何判断何时调用另一个类中的函数

时间:2022-01-20 00:40:35

I have two Python classes, call them "C1" and "C2". Inside C1 is a function named "F1" and inside C2 is a function named "F2". Is there a way to execute F2 each time F1 is run without making a direct call to F2 from within F1? Is there some other mechanism by which to know when a function from inside another class has been called?

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

I welcome any suggestions, but would like to know of some way to achieve this without making an instance of C2 inside C1.

我欢迎任何建议,但想知道实现这一点的一些方法,而不在C1内部创建C2的实例。

6 个解决方案

#1


You can write a little helper decorator that will make the call for you. The advantage is that it's easy to tell who is going to call what by looking at the code. And you can add as many function calls as you want. It works like registering a callback function:

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

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


You can do aspect-oriented programming with function and method decorators since Python 2.2:

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

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

#3


I believe that what you are trying to do would fit into the realm of Aspect Oriented Programming. However I have never used this methodology and don't even know if it can/has been implemented in Python.

我相信你想要做的事情将适合面向方面编程的领域。但是我从未使用过这种方法,甚至不知道它是否可以/已经在Python中实现。

Edit I just took a look at the link I provided and saw that there are 8 Python implementations mentioned. So the hard work has already been done for you :-)

编辑我刚刚看了一下我提供的链接,发现有8个Python实现提到。所以已经为你做了很多努力:-)

#4


It really depends on why you don't want to call F2 directly from within F1. You could always create a third class (C3) which encapsulates both C1 and C2. When F3 is called, it will call both F1 and F2. This is known as the Mediator pattern - http://en.wikipedia.org/wiki/Mediator_pattern

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

#5


Not knowing what is you are trying to achieve, i would suggest taking a look at pydispatcher. It allows you to implement the Observer pattern

不知道你想要达到的是什么,我建议看看pydispatcher。它允许您实现Observer模式

Basically, you register F2 with the dispatcher so that it will be called when a specific 'signal' is emitted. Your F1 'emits a signal' that says "I've been called". The dispatcher then calls F2 (or any number of functions that have registered themselves with that particular signal). Its actually really simpler than it sounds, easy to use, and de-couples your code (F1 does not need to know about F2).

基本上,您将F2与调度程序一起注册,以便在发出特定“信号”时调用它。你的F1'会发出一个信号,上面写着“我被称为”。然后,调度员调用F2(或任何已经使用该特定信号注册的功能)。它实际上比它听起来更简单,易于使用,并且解耦你的代码(F1不需要知道F2)。

(arhh.. I'm a new user and not allowed to include hyperlinks, but pydispatcher is easy to google for)

(arhh ..我是新用户,不允许包含超链接,但pydispatcher很容易google for)

#6


You catch all accesses to F1 with __getattr__ . This will allow you to do extra processing or return your own function in place of F1

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

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

I should warn you that this will call C2.F2 even if F1 is only being accessed (not run). It's rare but not impossible that F1 might simply be accessed for another purpose like f = myC1.F1 . To run F2 only on a call of F1 you need to expand this example to combine F2 with the returned function object. in other words:

我应该警告你,即使只是访问F1(不运行),这也会调用C2.F2。很少但并非不可能只是为了f = myC1.F1之类的其他目的而访问F1。要仅在F1调用时运行F2,您需要展开此示例以将F2与返回的函数对象组合。换一种说法:

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

#1


You can write a little helper decorator that will make the call for you. The advantage is that it's easy to tell who is going to call what by looking at the code. And you can add as many function calls as you want. It works like registering a callback function:

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

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


You can do aspect-oriented programming with function and method decorators since Python 2.2:

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

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

#3


I believe that what you are trying to do would fit into the realm of Aspect Oriented Programming. However I have never used this methodology and don't even know if it can/has been implemented in Python.

我相信你想要做的事情将适合面向方面编程的领域。但是我从未使用过这种方法,甚至不知道它是否可以/已经在Python中实现。

Edit I just took a look at the link I provided and saw that there are 8 Python implementations mentioned. So the hard work has already been done for you :-)

编辑我刚刚看了一下我提供的链接,发现有8个Python实现提到。所以已经为你做了很多努力:-)

#4


It really depends on why you don't want to call F2 directly from within F1. You could always create a third class (C3) which encapsulates both C1 and C2. When F3 is called, it will call both F1 and F2. This is known as the Mediator pattern - http://en.wikipedia.org/wiki/Mediator_pattern

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

#5


Not knowing what is you are trying to achieve, i would suggest taking a look at pydispatcher. It allows you to implement the Observer pattern

不知道你想要达到的是什么,我建议看看pydispatcher。它允许您实现Observer模式

Basically, you register F2 with the dispatcher so that it will be called when a specific 'signal' is emitted. Your F1 'emits a signal' that says "I've been called". The dispatcher then calls F2 (or any number of functions that have registered themselves with that particular signal). Its actually really simpler than it sounds, easy to use, and de-couples your code (F1 does not need to know about F2).

基本上,您将F2与调度程序一起注册,以便在发出特定“信号”时调用它。你的F1'会发出一个信号,上面写着“我被称为”。然后,调度员调用F2(或任何已经使用该特定信号注册的功能)。它实际上比它听起来更简单,易于使用,并且解耦你的代码(F1不需要知道F2)。

(arhh.. I'm a new user and not allowed to include hyperlinks, but pydispatcher is easy to google for)

(arhh ..我是新用户,不允许包含超链接,但pydispatcher很容易google for)

#6


You catch all accesses to F1 with __getattr__ . This will allow you to do extra processing or return your own function in place of F1

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

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

I should warn you that this will call C2.F2 even if F1 is only being accessed (not run). It's rare but not impossible that F1 might simply be accessed for another purpose like f = myC1.F1 . To run F2 only on a call of F1 you need to expand this example to combine F2 with the returned function object. in other words:

我应该警告你,即使只是访问F1(不运行),这也会调用C2.F2。很少但并非不可能只是为了f = myC1.F1之类的其他目的而访问F1。要仅在F1调用时运行F2,您需要展开此示例以将F2与返回的函数对象组合。换一种说法:

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