Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #100096 > unrolled thread
| Started by | Tony van der Hoff <tony@vanderhoff.org> |
|---|---|
| First post | 2015-12-07 18:10 +0000 |
| Last post | 2015-12-09 12:04 +1100 |
| Articles | 20 on this page of 21 — 11 participants |
Back to article view | Back to comp.lang.python
Accessing container's methods Tony van der Hoff <tony@vanderhoff.org> - 2015-12-07 18:10 +0000
Re: Accessing container's methods Rob Gaddi <rgaddi@highlandtechnology.invalid> - 2015-12-07 18:21 +0000
Re: Accessing container's methods Michael Torrie <torriem@gmail.com> - 2015-12-07 11:36 -0700
Re: Accessing container's methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-12-07 20:03 +0100
Re: Accessing container's methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-12-07 19:46 +0100
Re: Accessing container's methods Peter Otten <__peter__@web.de> - 2015-12-07 19:59 +0100
Re: Accessing container's methods Ian Kelly <ian.g.kelly@gmail.com> - 2015-12-07 12:33 -0700
Re: Accessing container's methods Terry Reedy <tjreedy@udel.edu> - 2015-12-07 16:38 -0500
Re: Accessing container's methods Chris Angelico <rosuav@gmail.com> - 2015-12-08 09:02 +1100
Re: Accessing container's methods Erik <python@lucidity.plus.com> - 2015-12-07 23:47 +0000
Re: Accessing container's methods Tony van der Hoff <tony@vanderhoff.org> - 2015-12-08 12:35 +0000
Re: Accessing container's methods [solved] Tony van der Hoff <tony@vanderhoff.org> - 2015-12-08 13:46 +0000
Re: Accessing container's methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-12-08 20:02 +0100
Re: Accessing container's methods Vincent Vande Vyvre <vincent.vande.vyvre@telenet.be> - 2015-12-08 20:54 +0100
Re: Accessing container's methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-12-08 23:51 +0100
Re: Accessing container's methods Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-12-08 20:30 +0000
Re: Accessing container's methods Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-12-08 23:52 +0100
Re: Accessing container's methods Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-12-08 22:59 +0000
Re: Accessing container's methods Erik <python@lucidity.plus.com> - 2015-12-08 22:37 +0000
Re: Accessing container's methods Ian Kelly <ian.g.kelly@gmail.com> - 2015-12-08 16:41 -0700
Re: Accessing container's methods Chris Angelico <rosuav@gmail.com> - 2015-12-09 12:04 +1100
Page 1 of 2 [1] 2 Next page →
| From | Tony van der Hoff <tony@vanderhoff.org> |
|---|---|
| Date | 2015-12-07 18:10 +0000 |
| Subject | Accessing container's methods |
| Message-ID | <dcm0c2Fi2ktU1@mid.individual.net> |
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
[toc] | [next] | [standalone]
| From | Rob Gaddi <rgaddi@highlandtechnology.invalid> |
|---|---|
| Date | 2015-12-07 18:21 +0000 |
| Message-ID | <n44inp$6gj$1@dont-email.me> |
| In reply to | #100096 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Michael Torrie <torriem@gmail.com> |
|---|---|
| Date | 2015-12-07 11:36 -0700 |
| Message-ID | <mailman.26.1449513733.12405.python-list@python.org> |
| In reply to | #100096 |
On 12/07/2015 11:10 AM, 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? You could add an attribute to each embedded object that provides a reference back to the container object. All in all, this design has a kind of smell to it. Would it not be better to ask the container class for information about the children, rather than the other way around? If a piece of code holds a reference to the child object then it must also by definition hold a reference to the container object, so why can't it ask the container object directly?
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-12-07 20:03 +0100 |
| Message-ID | <9541165.BHaEqqM5qn@PointedEars.de> |
| In reply to | #100099 |
Michael Torrie wrote: > On 12/07/2015 11:10 AM, Tony van der Hoff wrote: >> 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? > > You could add an attribute to each embedded object that provides a > reference back to the container object. ACK. > All in all, this design has a kind of smell to it. Would it not be > better to ask the container class for information about the children, > rather than the other way around? If a piece of code holds a reference > to the child object then it must also by definition hold a reference to > the container object, so why can't it ask the container object directly? Indeed, in this example asking the parent would be the best approach because only the number of actors is requested. That number should not change, and if it can change, then there should be an interface for that (a public method), in which the parent must update it. So Monty.count_actors() does not have to count the actors each time it is called from Actor.get_name(); it just has to return the value of a private attribute containing the current count. In other cases asking the parent would avoid inconsistencies, but that could be at the cost of efficiency; for example, a search for each child object, which does not scale well. -- PointedEars Twitter: @PointedEars2 Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-12-07 19:46 +0100 |
| Message-ID | <90599474.m2LfGONAbA@PointedEars.de> |
| In reply to | #100096 |
Tony van der Hoff wrote: > I have a class A, containing embedded embedded classes, which need to > access methods from A. Let the name of the "embedded class" (which is not embedded at all in your example code) be E. You could either store the information in the E instance upon or after construction, or you could pass a reference to the A instance to the E instance’s method, so that you can call the A instance’s public methods from the E instance’s methods. But consider the Law of Demeter. > 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. It would simply be wrong. Monty (Python) is (literally) a group of Actors. -- PointedEars Twitter: @PointedEars2 Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2015-12-07 19:59 +0100 |
| Message-ID | <mailman.27.1449514812.12405.python-list@python.org> |
| In reply to | #100096 |
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
I think I've seen the solution a long time a go in a Borland library -- a
Collection and a CollectionItem class, the latter with a reference to the
collection it belongs to. However, you are introducing a reference cycle,
and a simpler solution like putting a print_actor() method into the Monty
class is probably the way to go.
Anyway, here's a variant of your code using the back reference (and a few
cosmetical changes):
__metaclass__ = type # python 2 compatibility
class Monty:
def __init__(self, names):
self.actors = []
for id, name in enumerate(names, 1):
Actor(name, id, container=self)
def __len__(self):
return len(self.actors)
def __iter__(self):
for actor in self.actors:
yield actor
def remove(self, actor):
raise NotImplementedError
def add(self, actor):
self.actors.append(actor)
class Actor:
def __init__ (self, name, id, container=None):
self.name = name
self.id = id
self._container = None
self.container = container
def get_container(self):
return self._container
def set_container(self, container):
if self._container is not None:
self._container.remove(self)
if container is not None:
container.add(self)
self._container = container
container = property(get_container, set_container)
def __repr__(self):
return "I'm Actor {} Number {} of {}".format(
self.name, self.id, len(self.container))
if __name__ == '__main__':
o = Monty( ["Cleese", "Idle", "Palin" ])
print("number: {}".format(len(o)))
for l in o:
print(l)
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2015-12-07 12:33 -0700 |
| Message-ID | <mailman.28.1449516863.12405.python-list@python.org> |
| In reply to | #100096 |
On Mon, Dec 7, 2015 at 11:10 AM, Tony van der Hoff <tony@vanderhoff.org> 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? I'm guessing that you're coming from Java. Java has two different types of nested classes: non-static, where an instance of the inner class is implicitly associated with an instance of the outer class; and static, where an instance of the inner class is unrelated to any instance of the outer class. It looks like you're trying to do the former, but Python only has the static type of nested classes. So how would you go about creating a nested class of the non-static type? Make the association explicit. When Monty creates an Actor, pass it self as one of the arguments. Actor can then save that instance of Monty in an attribute and call the method thusly. As others have noted, this does create a reference cycle. The Python garbage collector is fine with cleaning up reference cycles as long as there are no objects __del__ methods anywhere in the cycle, so it's up to you whether you consider that to be a problem or not.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2015-12-07 16:38 -0500 |
| Message-ID | <mailman.31.1449524372.12405.python-list@python.org> |
| In reply to | #100096 |
On 12/7/2015 1:10 PM, 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! This is actually a case for using enumerate: for i, name in enumerate(names): > > 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 return list(self.actors) # or perhaps even faster return self.actors[:] > # define the inner class > class Actor: > def __init__ ( self, name, id ): > self.name = name > self.id = id Tkinter, and I presume tk, works by creating circular references. widgets get a reference to a master widget, and container get a reference to widgets that are placed (or packed or gridded) therein. Widgets have an explicit .destroy method (inherited from tcl/tk) to undo the circularity. It works, but it is not completely without problems. -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-12-08 09:02 +1100 |
| Message-ID | <mailman.36.1449525755.12405.python-list@python.org> |
| In reply to | #100096 |
On Tue, Dec 8, 2015 at 8:38 AM, Terry Reedy <tjreedy@udel.edu> wrote: >> def list_actors( self ): >> h=[] >> for n in self.actors: >> h.append( n.get_name() ) >> return h > > > return list(self.actors) # or perhaps even faster > return self.actors[:] Not identical semantics. This is a use-case for a comprehension: return [n.get_name() for n in self.actors] (although I would eschew the getter in favour of just "n.name") ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Erik <python@lucidity.plus.com> |
|---|---|
| Date | 2015-12-07 23:47 +0000 |
| Message-ID | <mailman.41.1449532084.12405.python-list@python.org> |
| In reply to | #100096 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Tony van der Hoff <tony@vanderhoff.org> |
|---|---|
| Date | 2015-12-08 12:35 +0000 |
| Message-ID | <dco155F2qipU1@mid.individual.net> |
| In reply to | #100120 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Tony van der Hoff <tony@vanderhoff.org> |
|---|---|
| Date | 2015-12-08 13:46 +0000 |
| Subject | Re: Accessing container's methods [solved] |
| Message-ID | <dco591F3qbqU1@mid.individual.net> |
| In reply to | #100120 |
Hum, sorry about the empty reply; just finger trouble!
Anyway I wasn't expecting such a great response; thanks to all.
On 07/12/15 23:47, Erik wrote:
[snip]
> 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 ) )
>
Whilst I'm grateful for all the responses, this is the one that got me
out of the hole I dug myself into.
In fact, this is precisely what I tried previously, and got:
TypeError: 'instancemethod' object has no attribute '__getitem__'
In my naivety, I concluded that this meant I couldn't use the 'self'
pointer in this way. However, trying it with the Monty example, it
worked fine, and I have now tracked down my error elsewhere.
>
> 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 ...
>
Yes, I guess it's quite nasty, but, in the non-trivial case, I'm only
calling for dynamic data from the parent, and not modifying it in any
way, so I think I can get away with it. Otherwise, I'd have to pass a
vast list of initialization data to the (many) children, and keep that
up to date by passing it down the line to each one, just in case it's
required, which would slow down things excessively. I know that if a
design doesn't feel comfortable, then it's probably wrong, but I believe
that in this case it's probably the best way forward.
>
> 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 rather liked Terry's suggestion of using enumerate.
The comment was tounge-in-cheek: Referring to an earlier thread, I'm yet
to be convinced that Python is better for not having
pre/post-increment/decrement operators. But, hey, I'm sure better minds
than mine have addressed the subject ;)
> (I assume you're using Python 3 because of your print statement - in
> Python 3, 'itertools.izip' should just be 'zip'.)
No, Im actually stuck on Python 2.7. I don't see how you jumped to that
conclusion from a simple print statement.
On 07/12/15 21:38, Terry Reedy wrote:
[snip]
> This is actually a case for using enumerate:
> for i, name in enumerate(names):
>
I've not come across this previously, but shall certainly use it in
future. Thanks!
> return list(self.actors) # or perhaps even faster
> return self.actors[:]
That doesn't seem to work:
<__main__.Actor instance at 0x7fc7478ba560>
<__main__.Actor instance at 0x7fc7478ba5a8>
<__main__.Actor instance at 0x7fc7478ba5f0>
Anyway, I'm no longer in a hole; thanks for all the excellent help. I'll
certainly review the design of my current project, to see if it can be
improved.
Cheers, Tony
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-12-08 20:02 +0100 |
| Message-ID | <5516674.oipO6xLiNU@PointedEars.de> |
| In reply to | #100120 |
Erik wrote:
^^^^
Please fix, Erik #75656.
> 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
NAK. All kinds of objects already "know" which container they are in.
> (let alone its "index" or "key" in that container).
That is a different issue.
> Amongst other things, you can't put the object into multiple containers
You could if you made it a list of container references.
> 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
It is the container’s job to make sure that this does not happen.
>> 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,
You can. Quickhack:
class Child:
self._parents = []
def add_to_parent (self, parent):
self._parents.append(parent)
self._parents = list(set(self._parents))
def get_parents (self)
return self._parents
class Parent:
self._children = []
def add_child (self, child):
self._children.append(child)
child.add_to_parent(self)
| >>> p = Parent()
| >>> c = Child()
| >>> p.add_child(c)
| >>> p2 = Parent()
| >>> p2.add_child(c)
| >>> c.get_parents()
| [p, p2]
“As a child, I want to know who my parents are.”
Certainly you will not deny the validity of that user story ;-)
--
PointedEars
Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Vincent Vande Vyvre <vincent.vande.vyvre@telenet.be> |
|---|---|
| Date | 2015-12-08 20:54 +0100 |
| Message-ID | <mailman.75.1449604867.12405.python-list@python.org> |
| In reply to | #100171 |
Le 08/12/2015 20:02, Thomas 'PointedEars' Lahn a écrit : > Erik wrote: > ^^^^ > Please fix, Erik #75656. > >> 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 > NAK. All kinds of objects already "know" which container they are in. > >> (let alone its "index" or "key" in that container). > That is a different issue. > >> Amongst other things, you can't put the object into multiple containers > You can. Quickhack: > > class Child: > self._parents = [] > > def add_to_parent (self, parent): > self._parents.append(parent) > self._parents = list(set(self._parents)) > > def get_parents (self) > return self._parents > > class Parent: > self._children = [] > ..... I thing you should test your code before post it. >>> class Child: ... self.parents = [] ... Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in Child NameError: name 'self' is not defined
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-12-08 23:51 +0100 |
| Message-ID | <3619885.mg2BhAsQCr@PointedEars.de> |
| In reply to | #100172 |
Vincent Vande Vyvre wrote:
> Le 08/12/2015 20:02, Thomas 'PointedEars' Lahn a écrit :
>> Erik wrote:
>>> Amongst other things, you can't put the object into multiple containers
>> You can. Quickhack:
^^^^^^^^^
>> class Child:
>> self._parents = []
>>
>> def add_to_parent (self, parent):
>> self._parents.append(parent)
>> self._parents = list(set(self._parents))
>>
>> def get_parents (self)
>> return self._parents
>>
>> class Parent:
>> self._children = []
>> .....
> I thing you should test your code before post it.
I _think_ you should read postings more carefully before replying to them.
> >>> class Child:
> ... self.parents = []
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 2, in Child
> NameError: name 'self' is not defined
Can be fixed easily by omitting “self.” there; likewise in Parent. (In
other programming languages I know, you need to refer to the class/instance
explicitly to which you add attributes/properties.)
--
PointedEars
Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Mark Lawrence <breamoreboy@yahoo.co.uk> |
|---|---|
| Date | 2015-12-08 20:30 +0000 |
| Message-ID | <mailman.76.1449606629.12405.python-list@python.org> |
| In reply to | #100171 |
On 08/12/2015 19:02, Thomas 'PointedEars' Lahn wrote: > Erik wrote: > ^^^^ > Please fix, Erik #75656. > Please fix what? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2015-12-08 23:52 +0100 |
| Message-ID | <8148791.79CPUYHJkR@PointedEars.de> |
| In reply to | #100173 |
Mark Lawrence wrote: > On 08/12/2015 19:02, Thomas 'PointedEars' Lahn wrote: >> Erik wrote: >> ^^^^ >> Please fix, Erik #75656. > > Please fix what? You are not ready for the answer yet. -- PointedEars Twitter: @PointedEars2 Please do not cc me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Mark Lawrence <breamoreboy@yahoo.co.uk> |
|---|---|
| Date | 2015-12-08 22:59 +0000 |
| Message-ID | <mailman.79.1449615617.12405.python-list@python.org> |
| In reply to | #100177 |
On 08/12/2015 22:52, Thomas 'PointedEars' Lahn wrote: > Mark Lawrence wrote: > >> On 08/12/2015 19:02, Thomas 'PointedEars' Lahn wrote: >>> Erik wrote: >>> ^^^^ >>> Please fix, Erik #75656. >> >> Please fix what? > > You are not ready for the answer yet. > I'll be all pointed ears when you actually manage to provide an answer to anything here. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
[toc] | [prev] | [next] | [standalone]
| From | Erik <python@lucidity.plus.com> |
|---|---|
| Date | 2015-12-08 22:37 +0000 |
| Message-ID | <mailman.78.1449614324.12405.python-list@python.org> |
| In reply to | #100171 |
Annoyingly, there seemed to be no responses to the original question
when I wrote that and then shortly after, I saw all the others (and we
all pretty much said the same thing - so I'm not sure why I was singled
out for special attention ;)).
On 08/12/15 19:02, Thomas 'PointedEars' Lahn wrote:
> Erik wrote:
> ^^^^
> Please fix, Erik #75656.
Fixed(*)
Thomas 'PointerEars', you have chosen to selectively quote snippets of
code and comments out of context, so I think it's futile to respond to
those arguments individually. The original request (if you read it) was
to return a string that said, essentially, "I am element 2 of 3 in my
container".
You posted a "Quickhack" (which, to be fair, is an accurate description)
which is incomplete, has errors and makes no sense in the context of the
original question. We all know we can create a list in Python (of parent
objects or whatever), but I think that if you expanded on that class a
bit more (methods for the containers to update the contained objects on
just what their index/key is etc) that you'll soon realise it's not a
scalable option.
Also, WRT the original question, what is the method supposed to return
now? "I am element 0 of 3 in container <FOO>, key 'bar' of ('bar',
'foo', 'spam') in container <BAR>"? Just curious.
I'm interested in this response though:
>> Generally, an object should not need to know which container it's in
>
> NAK. All kinds of objects already "know" which container they are in.
Please elucidate. Examples from the standard library would be interesting.
E.
(*) In the sense that it's not going to change ;)
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2015-12-08 16:41 -0700 |
| Message-ID | <mailman.80.1449618128.12405.python-list@python.org> |
| In reply to | #100171 |
On Tue, Dec 8, 2015 at 3:37 PM, Erik <python@lucidity.plus.com> wrote: > On 08/12/15 19:02, Thomas 'PointedEars' Lahn wrote: >> >> Erik wrote: >> ^^^^ >> Please fix, Erik #75656. > > > Fixed(*) [SNIP] > (*) In the sense that it's not going to change ;) Then I think you mean "Working as Intended", not "Fixed". B-)
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web