Common data area

Alex Martelli aleaxit at yahoo.com
Fri Oct 13 11:21:26 EDT 2000


"Dale Strickland-Clark" <dale at out-think.NOSPAMco.uk> wrote in message
news:ql3eusk2u1l4jgq1ejj8nnofruad2vs2u1 at 4ax.com...
> How can a bunch of objects share a common data area without having to
> pass a reference to it whenever a new instance is created?

By getting that reference from somewhere else, rather than
as one of __init__'s arguments.


> objA creates instance of objB which then creates instance of objC -
> etc.
>
> objB and ObjC both need read access to instance variables in objA
>
> Currently, each class passes a 'self' reference to each instance it
> creates but this is proving to be a bit messy.

It's no doubt the cleanest approach.  I don't see where the
"messiness" comes in having that one argument.


> Is there a better way I can make class instance objA available

No, but there is no dearth of *different* ways (not better --
actually, rather worse -- but, different).

One group of possibilities: the instance of objA registers
itself once as "the current creator object" and all instances
of objB, objC, etc, fetch the "reference to current creator
object" whenever they need it to set as their self.creator
instance variable.

The "register" and "fetch" can happen several ways; simplest
is probably:
to "register as the current creator object":
    ObjB.current_creator = self
to "fetch the current creator object":
    self.my_creator = ObjB.current_creator
i.e., stash away that reference in a class-variable of the
only class being created directly from objA's code, and
let everybody else fetch it from there.

I fail to see how, say:
    ObjB.current_creator = self
    self.objB = ObjB("foo", "bar")
can ever possibly be any better than, say:
    self.objB = ObjB("foo", "bar", creator=self)
but if you're using the latter and find it "messy", then
the former or some variation on it is your alternative.

You could have other fancier "register me as the current
creator" idioms, to partially remedy some of the various
defect of the approach, but adding complications on top
will never give you back the simplicity of the current
approach -- just consider that ObjB's __init__ can quite
obviously have a "creator=None" keyword argument and
start with a
    if creator: ObjB.current_creator = creator
to see that, whatever you can do with an "explicit
registration by the creator/client" idiom, you can ALSO
do (better) with a "creator passes self during creation
call" idiom (i.e., the idiom you're currently using!),
although not vice versa.

It IS, of course, possible to get seriously fancy...:

def creator():
    import sys
    try: raise RuntimeError
    except: return sys.exc_info()[2].tb_frame.f_back.f_back.f_locals['self']

class Try():
    def __init__(self):
        self.c = creator()

class A:
    def __init__(self):
        self.x = Try()

class B:
    def __init__(self):
        self.x = Try()

a=A()
b=B()

a.x.c
<A instance at 013566CC>
b.x.c
<B instance at 01352E3C>

So, Try's __init__ IS able to determine the 'self' of the object
that created it without requiring that it be passed as an explicit
argument, IF you're really keen to do it...

...but my advice to you is that you AVOID using such super-fancy
(and fragile) approaches.  They're great to play with, and to
impress friends with the utter power of Python's "introspection"...
but I wouldn't want them in my production/needing-maintenance code!

*SIMPLICITY* is an often-overlooked, but crucial, quality of any
piece of software -- think how much of said "Python's utter power"
comes from the very simplicity of its architecture.  Why not have
that quality in YOUR software, too...?  *Do the simplest thing
that can possibly work*.  Here, the simplest thing is clearly to
pass self as a parameter... therefore, that's what I suggest.


Alex






More information about the Python-list mailing list