Discussion:
[Tutor] Does composition only work with particular instances of objects?
boB Stepp
2015-08-14 04:31:17 UTC
Permalink
I was looking at an example illustrating composition from the book,
def __init__(self, description):
self.description = description
def __init__(self, length):
self.length = length
def __init__(self, bill, tail):
self.bill = bill
self.tail = tail
def about(self):
print('This duck has a', bill.description, 'bill and a',
tail.length, 'tail.')

Here I was mildly surprised that bill and tail were not Bill and Tail,
and in the about method that self.bill was not used in place of
bill.description, etc.
tail = Tail('long')
bill = Bill('wide orange')
duck = Duck(bill, tail)
duck.about()
This duck has a wide orange bill and a long tail.
bill0 = Bill('narrow rainbow')
tail0 = Tail('ginormous')
duck.about()
This duck has a wide orange bill and a long tail.
duck0 = Duck(bill0, tail0)
duck0.about()
This duck has a wide orange bill and a long tail.

From this I am forced to conclude that composition will only work with
particular instances of objects and not with any old objects created
from their respective classes. Is this understanding correct?

Thanks!
--
boB
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Zachary Ware
2015-08-14 04:46:32 UTC
Permalink
Post by boB Stepp
I was looking at an example illustrating composition from the book,
self.description = description
self.length = length
self.bill = bill
self.tail = tail
print('This duck has a', bill.description, 'bill and a',
tail.length, 'tail.')
Here I was mildly surprised that bill and tail were not Bill and Tail,
and in the about method that self.bill was not used in place of
bill.description, etc.
Something went wrong here, either with the example itself or your
copying of it. Your instinct is correct, it should be
'self.bill.description' rather than 'bill.description': the Duck.about
method as written above will only work in situations where 'bill' and
'tail' happen to be defined in the calling scope. The about method
should be:

def about(self):
print('This duck has a', self.bill.description,
'bill and a', self.tail.length, 'tail.')
Post by boB Stepp
tail = Tail('long')
bill = Bill('wide orange')
duck = Duck(bill, tail)
duck.about()
This duck has a wide orange bill and a long tail.
Before you fix the about method as I suggested above, try this again
but do `del bill, tail` before you call `duck.about()`; the failure
may be somewhat enlightening.
Post by boB Stepp
bill0 = Bill('narrow rainbow')
tail0 = Tail('ginormous')
duck.about()
This duck has a wide orange bill and a long tail.
duck0 = Duck(bill0, tail0)
duck0.about()
This duck has a wide orange bill and a long tail.
From this I am forced to conclude that composition will only work with
particular instances of objects and not with any old objects created
from their respective classes. Is this understanding correct?
Very much not :). You were correct to think this was meant to give
you 'This duck has a narrow rainbow bill and a ginormous tail.', but
the about method had a serious bug.
--
Zach
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
boB Stepp
2015-08-14 05:25:31 UTC
Permalink
On Thu, Aug 13, 2015 at 11:46 PM, Zachary Ware
Post by Zachary Ware
Post by boB Stepp
I was looking at an example illustrating composition from the book,
self.description = description
self.length = length
self.bill = bill
self.tail = tail
print('This duck has a', bill.description, 'bill and a',
tail.length, 'tail.')
Here I was mildly surprised that bill and tail were not Bill and Tail,
and in the about method that self.bill was not used in place of
bill.description, etc.
Well, I was wrong about "Bill" and "Tail", but, then again, that came
from trying to make the flawed example work as I thought it should
work with things like:

class Duck:
def __init__(self, Bill, Tail):
self.bill = Bill.__init__.description
etc.

Which, of course, I could not make work. But I should have explored
adding the "self" where I thought it should have been used.
Post by Zachary Ware
Something went wrong here, either with the example itself or your
copying of it...
Alas, it is an error in the book. The only alteration I made in the
author's code was to drop the parentheses after the class names, that
is, I used "class Bill:" instead of the author's "class Bill():". I
also added a "." after "'tail'" in the about method, but that truly is
an itty, bitty thing.
Post by Zachary Ware
...Your instinct is correct, it should be
'self.bill.description' rather than 'bill.description': the Duck.about
method as written above will only work in situations where 'bill' and
'tail' happen to be defined in the calling scope. The about method
print('This duck has a', self.bill.description,
'bill and a', self.tail.length, 'tail.')
Post by boB Stepp
tail = Tail('long')
bill = Bill('wide orange')
duck = Duck(bill, tail)
duck.about()
This duck has a wide orange bill and a long tail.
Before you fix the about method as I suggested above, try this again
but do `del bill, tail` before you call `duck.about()`; the failure
may be somewhat enlightening.
Yeah, I was dead certain that the book's example as written would only
work for the particular objects "bill" and "tail" and not for any
objects used for those in "Duck(bill, tail)" and this made absolutely
no sense to me. Why limit composition to work with only particular
instances of objects??? I probably should have gone ahead and played
with the substitutions you suggested. "bill.description" and
"tail.length" just did not make any sense to me.

Thanks, Zach! I will have to see if the book has an errata site.

boB
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Alan Gauld
2015-08-14 07:50:23 UTC
Permalink
Post by boB Stepp
I was looking at an example illustrating composition from the book,
self.description = description
self.length = length
self.bill = bill
self.tail = tail
print('This duck has a', bill.description, 'bill and a',
tail.length, 'tail.')
Here I was mildly surprised that bill and tail were not Bill and Tail,
and in the about method that self.bill was not used in place of
bill.description, etc.
tail = Tail('long')
bill = Bill('wide orange')
duck = Duck(bill, tail)
duck.about()
This duck has a wide orange bill and a long tail.
This is a rubbish example, or at the kindest an incomplete one.
The problem here is that the class about() method is relying on the
existence of global variables called bill and tail.
In any sane example it should be using the attributes self.bill and
self.tail.

If they really did want all instances to share the same bill and tail
they should have made them class variables rather than instance ones and
used those in about().

So, in normal use of composition you, Bob, would be right and they
should use self.bill and self.tail.
Post by boB Stepp
bill0 = Bill('narrow rainbow')
tail0 = Tail('ginormous')
duck.about()
This duck has a wide orange bill and a long tail.
duck0 = Duck(bill0, tail0)
duck0.about()
This duck has a wide orange bill and a long tail.
This is because of the hard coded references to the global
vars bill and tail. If they used self.bill and self.tail
everything would work as you expected.

So, unless the book explains why this is bad practice and
goes on to show a good example, I must conclude its a very
bad example.
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
boB Stepp
2015-08-14 13:17:06 UTC
Permalink
Post by Alan Gauld
So, unless the book explains why this is bad practice and
goes on to show a good example, I must conclude its a very
bad example.
I found the errata pages for the book
(http://www.oreilly.com/catalog/errata.csp?isbn=0636920028659) and a
Jeff Bienstadt submitted this on Aug 05, 2015. Mr. Bienstadt did a
fine job of making his points. The author acknowledged his errors
with:

"Thanks for catching this. You are completely correct, and your
example code proves it. I regret the error. I would blame my cat, but
this one wasn't his fault."

So obviously the quality control process let this one slip through the cracks.
--
boB
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Loading...