holdenweb / int-py-notes

Notebooks from Intermediate Python videos
66 stars 56 forks source link

Decorator code results do not agree with commentary #4

Open holdenweb opened 10 years ago

holdenweb commented 10 years ago

In introducing-decorators.ipynb we apply a class decorator, barking(), to two instances, the first of a class with one applicable method, the second of a subclass of that class with two further applicable methods. This succeeds with the first class (the one with only one method) but fails with the second for reasons described below.

Although the commentary makes it appear the (very lightweight) testing performed succeeds, closer examination of the output reveals that the two additional methods are actually calling the same original method (wag()), and the the original code of the decorator has a bug.

This issue is caused by the use of a decorator-local variable to wrap each non-dunder method. Since the same variable is used to wrap each method, and since all methods are handled in a single call to the decorator, the wrapped functions must necessarily all be the same.

This explains why both d3.wag() and d3.sniff() print "a dog_3 is happy" - the wag() method is the last to be processed by the decorator, and is thus the function called by all decorated methods.

Note also that this example demonstrates that only locally-defined methods appear in the class's __dict__ - the inherited shout() method is not wrapped a second time.

Please comment and reassign to me for further discussion.

GanizaniSitara commented 10 years ago

It's great to come here and see the explanation. Thanks for taking the time to post the details!

holdenweb commented 10 years ago

Happy it's been helpful. The reports were anonymous, so I couldn't respond directly, and the O'Reilly Errata page appears to contain no functionality to action a reported error.