5

Is there no magic python way of accessing the instance of the class that has a reference to the current self inside it? ie:

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 being the magic bullet that does not exist. Is there a feature in python for this behaviour?

Yes I know I could pass a reference in to the constructor, but I'm looking for a more elegant solution.

Zv_oDD
  • 1,838
  • 1
  • 18
  • 26
  • If you're looking for mixins, that's not how you do it in python. – georg Mar 20 '12 at 12:39
  • 1
    this thread might be interesting then: http://stackoverflow.com/questions/115844/recommended-python-publish-subscribe-dispatch-module – georg Mar 20 '12 at 15:08

5 Answers5

4

No, You'd have to do something like this

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()
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
2

No, there is no nice way of doing this. Pass a reference in to the initializer.

To preclude questions, it's probably possible in most cases to find the owner heuristically by inspecting the stack, something like in this question. But it will be fragile, buggy and difficult to understand. And it goes against the "explicit > implicit" philosophy.

Community
  • 1
  • 1
Katriel
  • 120,462
  • 19
  • 136
  • 170
2

As far as I know such a feature does not exist. Also, passing it in as reference to the constructor and calling self.parent.say_hi() is much more explicit and (indeed) elegant. And explicit is better than implicit or using magic language features.

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
2

Technically, you can use sys._getframe:

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

But you should not do that. It's bound to lead to confusion, will break on new Python implementations, will complicate debugging, and is prone to break.
There's a reason why sys._getframe is listed in 5 Years of Bad Ideas.

Instead, pass a reference, either to the parent object, or to the say_hi method.

phihag
  • 278,196
  • 72
  • 453
  • 469
2

On the second thought, what you're looking for pretty closely resembles descriptors. Consider:

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

Here the agent is attached to two different instances and "knows" each time which instance wants to talk to him.

georg
  • 211,518
  • 52
  • 313
  • 390