Accessing container's methods

Tony van der Hoff tony at vanderhoff.org
Tue Dec 8 07:35:48 EST 2015


On 07/12/15 23:47, Erik wrote:
> Hi Tony,
>
> On 07/12/15 18:10, Tony van der Hoff wrote:
>> 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.
>
> Generally, an object should not need to know which container it's in
> (let alone its "index" or "key" in that container). Amongst other
> things, you can't put the object into multiple containers which might be
> organised differently and you are asking for bugs where the container
> and the object get out of sync WRT just where the object is in the
> container (in your example, if you found you wanted to add a method
> where the 'actors' list is modified (say, calling "self.actors.insert(3,
> ...)", or sorting the list) then things get nasty quickly.
>
> However, you've said this is a highly contrived example, so I'll bear
> with you and assume what you're trying to do is not quite as nasty as
> the example implies ;)
>
>> Can anyone please advise me on how to achieve this magic?
>
> As you can't sensibly put the object into more than one container at a
> time anyway, then you can pass the container object to the Actor object
> as its "parent". It can then call its parent object for things that the
> parent will know (such as, the total number of contained objects):
>
> class Actor:
>     def __init__ ( self, name, id, parent ):
>       self.name = name
>       self.id = id
>       self.parent = parent
>
>     def get_name( self ):
>       txt = "I'm Actor {} Number {} of {}".\
>                format(  self.name, self.id, self.parent.count_actors() )
>       return txt
>
> Then you can add a new actor with:
>
>    self.actors.append( Actor( n, i, self ) )
>
>
> Note that you are creating circular references here, too (the container
> references the Actor object and the Actor object references the
> container). Just another possible issue to bear in mind ...
>
>
> Also, while I'm looking at this, you have this loop and comment:
>
>  >    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!
>
> However, if you refactor that loop to use iterators, you don't need to
> manually manipulate 'i' at all (you need to import the itertools module
> first, and this is the "new" version where the container is passed in as
> the parent):
>
>      def __init__( self, names ):
>        self.actors = [ Actor ( n, i, self ) for n, i in
> itertools.izip(names, itertools.count()) ]
>
> Or, if you don't like list comprehensions:
>
>      def __init__( self, names ):
>        self.actors = []
>        for n, i in itertools.izip(names, itertools.count()):
>          self.actors.append( Actor( n, i, self ) )
>
> (I assume you're using Python 3 because of your print statement - in
> Python 3, 'itertools.izip' should just be 'zip'.)
> HTH,
> E.




More information about the Python-list mailing list