Как узнать, когда была вызвана функция в другом классе - PullRequest
2 голосов
/ 24 мая 2009

У меня есть два класса Python, назовите их «C1» и «C2». Внутри C1 находится функция с именем «F1», а внутри C2 - функция с именем «F2». Есть ли способ выполнить F2 каждый раз, когда запускается F1, без прямого вызова F2 изнутри F1? Есть ли какой-то другой механизм, с помощью которого можно узнать, когда была вызвана функция из другого класса?

Я приветствую любые предложения, но хотел бы знать, как этого добиться, не создавая экземпляр C2 внутри C1.

Ответы [ 6 ]

3 голосов
/ 24 мая 2009

Вы можете написать маленького помощника-декоратора, который будет звонить вам. Преимущество заключается в том, что с помощью кода можно легко определить, кто и как будет звонить. И вы можете добавить столько вызовов функций, сколько хотите. Это работает как регистрация функции обратного вызова:

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 голосов
/ 24 мая 2009

Это действительно зависит от того, почему вы не хотите вызывать F2 напрямую из F1. Вы всегда можете создать третий класс (C3), который включает в себя как C1, так и C2. Когда вызывается F3, он вызывает как F1, так и F2. Это называется паттерном посредника - http://en.wikipedia.org/wiki/Mediator_pattern

2 голосов
/ 24 мая 2009

Аспектно-ориентированное программирование можно выполнять с помощью декораторов функций и методов начиная с Python 2.2:

@decorator(decorator_args)
def functionToBeDecorated(function_args) :
    pass
2 голосов
/ 24 мая 2009

Я считаю, что то, что вы пытаетесь сделать, вписалось бы в область Аспектно-ориентированного программирования . Однако я никогда не использовал эту методологию и даже не знаю, может ли она быть реализована в Python.

Редактировать Я только что посмотрел на предоставленную мной ссылку и увидел, что упоминаются 8 реализаций Python . Так что тяжелая работа для вас уже проделана: -)

1 голос
/ 24 мая 2009

Не зная, чего вы пытаетесь достичь, я бы посоветовал взглянуть на pydispatcher. Позволяет реализовать шаблон Observer

По сути, вы регистрируете F2 у диспетчера, чтобы он вызывался при выдаче определенного «сигнала». Ваш F1 «испускает сигнал», который говорит: «Меня вызвали». Затем диспетчер вызывает F2 (или любое количество функций, которые зарегистрировались для этого конкретного сигнала). На самом деле он действительно проще, чем кажется, прост в использовании и разделяет ваш код (F1 не нужно знать о F2).

(арх ... Я новый пользователь и не могу включать гиперссылки, но pydispatcher легко найти в Google)

0 голосов
/ 24 мая 2009

Вы ловите все обращения к F1 с помощью __getattr__. Это позволит вам выполнить дополнительную обработку или вернуть собственную функцию вместо F1

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

Я должен предупредить вас, что это вызовет C2.F2, даже если F1 доступен только (не запущен). Редко, но не невозможно, чтобы к F1 можно было просто получить доступ для другой цели, такой как f = myC1.F1. Чтобы запустить F2 только при вызове F1, необходимо расширить этот пример, чтобы объединить F2 с возвращенным функциональным объектом. другими словами:

def F1F2():
   self.F1()
   C2.F2()
return F1F2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...