Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

object knows which object called it?

0 views
Skip to first unread message

Reckoner

unread,
Apr 6, 2009, 10:53:55 AM4/6/09
to
hi,

I have the following problem: I have two objects, say, A and B, which
are both legitimate stand-alone objects with lives of their own.

A contains B as a property, so I often do

A.B.foo()

the problem is that some functions inside of B actually need A
(remember I said they were both standalone objects), so I have to
often do:

A.B.foo_func(A)

Which is kind of awkward.

Is there some way that B.foo_func() could somehow know that it was
called as a property of A in this way?

Note that I'm looking for the calling object and NOT the calling
function.

Thanks in advance.

Message has been deleted

R. David Murray

unread,
Apr 6, 2009, 12:53:40 PM4/6/09
to pytho...@python.org

You could probably do this by creating a custom __getattr__ method (or
maybe even just a property) on A that would recognize B as an object and
return it wrapped in a class that would pick up the __getattr__ call on B
and translate it into a real call on B passing A as the first argument.

But that kind of magic is not considered good Python practice ("explicit
is better than implicit"). And it would be quite inefficient :)

I think the OO way to do this is to provide a method on A that does the
right thing:

def Bfoo_func(self):
self.B.foo_func(self)

Or maybe you could look at generic methods, which provide a way
to do multiple dispatch.

--
R. David Murray http://www.bitdance.com

Aaron Brady

unread,
Apr 6, 2009, 1:04:56 PM4/6/09
to

Hi Reckoner,

I believe this does what you want. It's an advanced technique and not
available in all OO languages.

class ClsA( object ):
def __init__( self ):
self.inst= None
def __get__( self, instance, owner ):
self.inst= instance
return self
def submethA( self, arg ):
print( 'submethA %r, instance %r'% ( arg, self.inst ) )

class ClsB( object ):
A= ClsA( )
def methA( self, arg ):
print( 'methA %r'% arg )

b= ClsB( )
b.methA( 'this' )
b.A.submethA( 'that' )

#Output:
'''
methA 'this'
submethA 'that', instance <__main__.ClsB object...>
'''

There's a small discussion in another today's thread, 'group several
methods under an attribute'.

Duncan Booth

unread,
Apr 6, 2009, 1:09:55 PM4/6/09
to
Reckoner <reck...@gmail.com> wrote:

You can do something like this if you really want (Zope does), but it is
complex and confusing (Zope 3 has dropped implicit acquisition as being a
bad idea). Have a look at
http://www.zope.org/Documentation/Books/ZDG/current/Acquisition.stx
which has the following example:

import ExtensionClass, Acquisition

class C(ExtensionClass.Base):
color='red'

class A(Acquisition.Implicit):

def report(self):
print self.color

a=A()
c=C()
c.a=A()

c.a.report() # prints 'red'

d=C()
d.color='green'
d.a=a

d.a.report() # prints 'green'

a.report() # raises an attribute error

and what you actually asked for: in the example above 'c.a.aq_parent is c'

If you want to confuse yourself you can install Zope's ExtensionClass and
Acquisition modules from PyPi:
http://pypi.python.org/pypi/Acquisition/2.12.0a1


Anthra Norell

unread,
Apr 6, 2009, 1:44:44 PM4/6/09
to pytho...@python.org
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>

B has to get into A somehow. Providing an installation method is no
inconvenience if one remembers later not to bypass it.


class A:
something_for_contained_to_show = 99
def install_contained (self, B):
B.container = self # Provides B with a reference to A
self.contained = B

class B:
def method_with_container_access (self):
print self.container # Show container object
print self.container.something_for_contained_to_show


>>> a = A (); b = B (); a.install_contained (b)
>>> b.method_with_container_access ()

<__main__.A instance at 0x019D5788>
99


Does this look like a good idea?


Frederic


George Sakkis

unread,
Apr 6, 2009, 3:55:17 PM4/6/09
to

Read up on descriptors [1], it seems that's what you're looking for.

HTH,
George

[1] http://users.rcn.com/python/download/Descriptor.htm

Steven D'Aprano

unread,
Apr 6, 2009, 10:19:42 PM4/6/09
to
On Mon, 06 Apr 2009 07:53:55 -0700, Reckoner wrote:

> hi,
>
> I have the following problem: I have two objects, say, A and B, which
> are both legitimate stand-alone objects with lives of their own.
>
> A contains B as a property, so I often do
>
> A.B.foo()
>
> the problem is that some functions inside of B actually need A (remember
> I said they were both standalone objects),

You contradict yourself.

If the methods inside B *need* A, then B is NOT a standalone object, it
has a dependency, namely A.

> so I have to often do:
>
> A.B.foo_func(A)
>
> Which is kind of awkward.
>
> Is there some way that B.foo_func() could somehow know that it was
> called as a property of A in this way?

Not in any nice way. There's probably some sort of deep evil black magic
that would work, for some definition of "work" that includes the phrase
"fragile, incomprehensible and risky".

The solution is to admit your dependency instead of living in denial, and
tell B who owns it:

B.owner = A

Now B.foo_func() can refer to B.owner and all is good.


For advanced work, you can make B.owner a weakref to A, and avoid
creating a reference cycle which can sometimes be tricky to deal with.

--
Steven

Ricardo Aráoz

unread,
Apr 7, 2009, 8:28:28 PM4/7/09
to pytho...@python.org
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>>
Maybe this would work for you?

>>> class B(object) :
... def __init__(self, owner=None) :
... self.owner = owner
... def someMethod(self) :
... print self.owner.name
...
>>> class A(object) :
... def __init__(self, name='class A') :
... self.B = B(owner=self)
... self.name = name
...
>>> instA1 = A('one')
>>> instA2 = A('two')
>>> instA1.B.someMethod()
one
>>> instA2.B.someMethod()
two
>>>


afr...@yahoo.co.uk

unread,
Apr 7, 2009, 9:16:07 PM4/7/09
to
On Apr 7, 2:53 am, "R. David Murray" <rdmur...@bitdance.com> wrote:

> I think the OO way to do this is to provide a method on A that does the
> right thing:
>
>     def Bfoo_func(self):
>         self.B.foo_func(self)
>
> Or maybe you could look at generic methods, which provide a way
> to do multiple dispatch.

+1

Which dispatch would itself be using methods to pass 'self' to the
receiving object. Yes this would seem to be the obvious way to
establish two-way communication between objects. I would be so bold
as to suggest that if the design the OP has adopted is not amenable to
this straightfoward approach, the design needs to be reassessed.

0 new messages