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