иерархия объектов Python; Ссылка на экземпляр владельца?

Нет ли волшебного способа Python для доступа к экземпляру класса, который имеет ссылку на текущее «я» внутри него? то есть:

class A(object):
    def __init__(self):
        self.B = B()

    def say_hi(self):
        print "Hi"

class B(object)
    def __init__(self):
        __get_owner_ref__.say_hi()

A()

get_owner_ref — чудодейственное средство, которого не существует. Есть ли функция в python для такого поведения?

Да, я знаю, что могу передать ссылку конструктору, но я ищу более элегантное решение.


person Zv_oDD    schedule 20.03.2012    source источник
comment
Если вы ищете миксины, это не то, как вы это делаете в python.   -  person georg    schedule 20.03.2012
comment
Вопрос в передаче сигналов между объектами без явной передачи ссылок. Не унаследованная функциональность или примеси.   -  person Zv_oDD    schedule 20.03.2012
comment
этот поток может быть интересен тогда: stackoverflow.com /вопросы/115844/   -  person georg    schedule 20.03.2012


Ответы (5)


Во-вторых, то, что вы ищете, очень похоже на дескрипторы. Рассмотреть возможность:

class Agent(object):
    def __get__(self, obj, objtype):
        print 'Agent %s called from %s ' % (id(self), obj.name)

class X(object):
    agent = Agent()

    def __init__(self, name):
        self.name = name

a = X('Foo')
a.agent

b = X('Bar')
b.agent

Здесь agent подключен к двум разным экземплярам и каждый раз «знает», какой экземпляр хочет поговорить с ним.

person georg    schedule 21.03.2012

Нет, вам нужно сделать что-то вроде этого

class A(object):
    def __init__(self):
        self.B = B(parent=self)

    def say_hi(self):
        print "Hi"

class B(object)
    def __init__(self, parent):
        self.parent = parent   # you don't need to do this, but it might be a good idea
        parent.say_hi()

A()
person John La Rooy    schedule 20.03.2012

Нет, нет хорошего способа сделать это. Передайте ссылку в инициализатор.

Чтобы избежать вопросов, вероятно, в большинстве случаев можно найти владельца эвристически, проверив стек, как в этот вопрос. Но он будет хрупким, глючным и сложным для понимания. И это противоречит принципу "явно > неявно".

person Katriel    schedule 20.03.2012

Насколько я знаю, такой функции не существует. Кроме того, передача его в качестве ссылки на конструктор и вызов self.parent.say_hi() намного более явный и (действительно) элегантный. И явное лучше, чем неявное или использование магических функций языка.

person Simeon Visser    schedule 20.03.2012

Технически вы можете использовать sys._getframe:

class B(object):
    def __init__(self):
        import sys
        a = sys._getframe(1).f_locals['self']
        a.say_hi()

Но этого делать не следует. Это неизбежно приведет к путанице, сломается в новых реализациях Python, усложнит отладку и может сломаться.
Есть причина, по которой sys._getframe указан в 5 лет плохих идей.

Вместо этого передайте ссылку либо на родительский объект, либо на метод say_hi.

person phihag    schedule 20.03.2012