tags:

views:

221

answers:

6

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?

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

+2  A: 

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.

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

Peter M
+2  A: 

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

@decorator(decorator_args)
def functionToBeDecorated(function_args) :
    pass
duffymo
+2  A: 

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

James
A: 

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

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:

def F1F2():
   self.F1()
   C2.F2()
return F1F2
SpliFF
+3  A: 

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
Nadia Alramli
+1  A: 

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

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

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

arcanum