Let's say I have two classes A and B:
Class A:
# A's attributes and methods here
Class B:
# B's attributes and methods here
Now I can assess A's properties in object of B class as follows:
a_obj = A()
b_obj = B(a_obj)
What I need is a two way access.
How do I access A's properties in B and B's properties in A ?
You need to create pointers either way:
class A(object):
parent = None
class B(object):
def __init__(self, child):
self.child = child
child.parent = self
Now A
can refer to self.parent
(provided it is not None
), and B
can refer to self.child
. If you try to make an instance of A
the child of more than one B
, the last 'parent' wins.
Why not just plan your objects in a way where this can be taken care of with inheritance.
class A(object):
# stuff
class B(A):
# has A methods/properties
class C(B):
# has A and B methods/properties
In this case by planing ahead, you could just use C
for a generalist object, and A
with B
as more specialised/bare parents.
This method will be very useful, as you can use objects of both the classes interchangeably. There is a serious problem with this, I ll explain that at the end.
class A:
def MethodA(self):
return "Inside MethodA"
def __init__ (self, Friend=None):
self.__dict__['a'] = "I am a"
self.__dict__['Friend'] = Friend
if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self
def __getattr__(self, name):
if self.Friend is not None: return getattr(self.Friend, name)
raise AttributeError ("Unknown Attribute `" + name + "`")
def __setattr__(self, name, value):
if self.Friend is not None: setattr(self.Friend, name, value)
raise AttributeError ("Unknown Attribute `" + name + "`")
class B:
def MethodB(self):
return "Inside MethodB"
def __init__ (self, Friend=None):
self.__dict__['b'] = "I am b"
self.__dict__['Friend'] = Friend
if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self
def __getattr__(self, name):
if self.Friend is not None: return getattr(self.Friend, name)
raise AttributeError ("Unknown Attribute `" + name + "`")
def __setattr__(self, name, value):
if self.Friend is not None: setattr(self.Friend, name, value)
raise AttributeError ("Unknown Attribute `" + name + "`")
Explanation:
As per this page, __getattr__
and __setattr__
will be invoked on python objects only when the requested attribute is not found in the particular object's space. So in the constructor we are establishing relationship between both the classes. And then whenever __getattr__
or __setattr__
is called, we refer the other object using getattr
method. (getattr, setattr) We use __dict__
to assign values in the constructor, so that we ll not call __setattr__
or __getattr__
.
Sample Runs:
b = B()
# print b.a # Throws AttributeError, as A and B are not related yet
a = A(b)
print a.a
print a.b
print b.a # Works fine here, as 'a' is not found b, returns A's a
print b.b
print a.MethodA()
print a.MethodB()
print b.MethodA()
print b.MethodB()
I am a
I am b
I am a
I am b
Inside MethodA
Inside MethodB
Inside MethodA
Inside MethodB
Now, the serious problem:
If we try to access an attribute which is not there in both these objects, we ll end up in infinite recursion. Lets say I want to access 'C' from 'a'. Since C is not in a, it will call __getattr__
and it will refer b object. As b object doesnt have C, it will call __getattr__
which will refer object a. So we end up in an infinite recursion. So this approach works fine, when you you don't access anything unknown to both the objects.