Объект вызова Introspect

Как я интроспективно просматриваю экземпляр 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

Ответ 1

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

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

  • Передайте вызывающий объект в качестве аргумента функции
  • Явно добавить дескриптор вызывающего на экземпляр 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 по любой причине.

Ответ 2

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

Ответ 3

Сделайте это, переработав свой код, чтобы работать как

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

Ответ 4

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

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