Accessing container's methods

Rob Gaddi rgaddi at highlandtechnology.invalid
Mon Dec 7 13:21:45 EST 2015


Tony van der Hoff wrote:

> Hi,
>
> I have a class A, containing embedded embedded classes, which need to 
> access methods from A.
> .
> A highly contrived example, where I'm setting up an outer class in a 
> Has-a relationship, containing a number of Actors. The inner class needs 
> to access a method of the outer class; here the method get_name.
>
> I don't really want to make Actor a sub-class (is-a; it isn't) of Monty; 
> that would raise all sorts of other problems.
>
> Can anyone please advise me on how to achieve this magic?
>
> # define the outer class
> class Monty:
>    def __init__( self, names ):
>      self.actors = []
>
>      i = 0
>      for n in names:
>        self.actors.append( Actor( n, i ) )
>        i += 1	# here is a case for python supporting post-increment!
>
>    def count_actors( self ):
>      return len( self.actors )
>
>    def list_actors( self ):
>      h=[]
>      for n in self.actors:
>        h.append( n.get_name() )
>      return h
>
> # define the inner class
> class Actor:
>    def __init__ ( self, name, id ):
>      self.name = name
>      self.id = id
>
>    def get_name( self ):
>
>      # and here lies the problem;
>      # AttributeError: Actor instance has no attribute 'count_actors'
>      # how do I access the method in the enclosing class
>      txt = "I'm Actor {} Number {} of {}".\
>               format(  self.name, self.id, self.count_actors() )
>
>      # this works, of course
>      #txt = "I'm Actor \"{}\"; Number {}.  ".\
> 		format( self.name, self.id )
>
>      return txt
>
> if __name__ == '__main__':
>    o = Monty( ["Cleese", "Idle", "Palin" ] )
>    print "number: ",o.count_actors()
>    a = o.list_actors()
>    for l in a:
>      print l
>
> Thanks, Tony

Ideally, you wouldn't.  The Actor's name is independent of the number of
them in the Monty, and all logic that needed to know about the full
Monty would be there in list_actors, not delegated down to the Actor. 
That way all your dependencies are unidirectional: a Monty has a lot
of expectations about an Actor but an Actor knows nothing about a
Monty.

And that's GREAT when you can make it work.  Sometimes, in non-contrived
examples, you get a situation where you can't avoid blending information
around in both directions.  In that case, your Monty instance is already
acting as a factory for Actors.  Keep going with that; have the Actor be
init'ed with a .monty that refers back to the Monty containing it.  It's
a circular reference, but you can either a) break that using weakref or
b) not care and trust Python's garbage collection to sort it all out
eventually.

-- 
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.



More information about the Python-list mailing list