Самоанализ вызывающего объекта - PullRequest
13 голосов
/ 01 сентября 2011

Как я могу проанализировать экземпляр A из b.func() (т.е. A экземпляр self):

class A():
    def go(self):
        b=B()
        b.func()

class B():
    def func(self):
        # Introspect to find the calling A instance here

Ответы [ 4 ]

25 голосов
/ 01 сентября 2011

Как правило, мы не хотим, чтобы func имел доступ к вызывающему экземпляру A, потому что это нарушает инкапсуляцию .Внутри b.func вы должны иметь доступ ко всем переданным аргументам и кваргам, состоянию / атрибутам экземпляра b (через self здесь) и любым глобальным переменным, висящим вокруг.

Если вы хотите узнать о вызывающем объекте, допустимыми путями являются:

  1. Передача вызывающего объекта в качестве аргумента функции
  2. Явно добавьтеобрабатывать вызывающий объект на b экземпляре перед использованием func, а затем обращаться к этому дескриптору через self.

Однако , с учетом этого отказа от ответственности, все же стоит знать, что возможности самоанализа python достаточно мощны для доступа к модулю вызывающей стороны в некоторых случаях.В реализации CPython вы можете получить доступ к вызывающему экземпляру A без изменения интерфейсов:

class A():
    def go(self):
        b=B()
        b.func()

class B():
    def func(self):
        import inspect
        print inspect.currentframe().f_back.f_locals['self']

if __name__ == '__main__':
    a = A()
    a.go()

Вывод:

<__main__.A instance at 0x15bd9e0>

Это может быть полезно узнатьо для отладки кода иногда.Но было бы неразумным дизайнерское решение когда-либо получить доступ к таким фреймам стека в случае, если B.func фактически необходимо было использовать A по любой причине.

5 голосов
/ 01 сентября 2011

Вы передаете его b.func() в качестве аргумента.

0 голосов
/ 01 сентября 2011

Я согласен с Бенджамином - передайте его b.func () в качестве аргумента и не анализируйте его !!!!

Если ваша жизнь действительно зависит от этого, тогда я думаю, что вы можете вывести ответ из этого ответа .

0 голосов
/ 01 сентября 2011

Сделайте это путем рефакторинга вашего кода, чтобы он работал как

class A():
    def go(self):
        b = B(self)
        b.func()

class B():
    def __init__(self, a):
        self.a = a

    def func(self):
        # Use self.a

или

class A():
    def go(self):
        b = B()
        b.func(self)

class B():
    def func(self, a):
        # a
...