Python class development toolkit
You'll probably recognize the name Raymond Hettinger if you lurk on the Python mailing-lists or have ever been to a Pycon event. He's a great speaker and has several great Python talks. I recently watched one of his talks from Pycon 2013 about class development. As usual, the talk is full of great tidbits for beginners and old-timers. There's a nice discussion on iterative class design and a few key features that aren't always touched on in books and tutorials:
__slots__ is not inherited by classes!
The real gem of knowledge, for me, was a discussion of name mangling that comes in at around the 33 minute mark where Mr. Hettinger, being a core developer, mentioned the initial reason behind the name mangling concept. It turns out name mangling was never meant to make things 'private' in the sense that things are 'private' in other Object Oriented languages like C++ and Java.
This 'private' misconception is something I've heard several times over the years. In fact, I looked around and found a good discussion of the initial concept behind name mangling from Guido himself. In short, the real purpose of the double underscore, dunder, is to make a 'class local reference.'
Remember, most of the time
self means you or your subclasses, but
occasionally you need it to be just you. In other words, it's meant as a way
to to verify that the
self in your method is actually who you think it is.
The video gives a good example:
class Circle(object): def __init__(self, radius): self.radius = radius def area(self): # This will call self.perimeter() which in the case of Tire is # Tire.perimeter(), not Circle.perimeter. p = self.perimeter() r = p / math.pi / 2.0 return math.pi * r ** 2.0 class Tire(Circle): def perimeter(self): return Circle.perimeter(self) * 1.25
This code makes it difficult to keep a local copy of our original
method since it could be overridden by subclasses. The naive solution to this
would be to do something like the following:
class Circle(object): def __init__(self, radius): self.radius = radius def area(self): # This will call self.perimeter() which in the case of Tire is # Tire.perimeter(), not Circle.perimeter. p = self.perimeter() r = p / math.pi / 2.0 return math.pi * r ** 2.0 _perimeter = perimeter
Of course, this doesn't really work because subclasses could also override this
_perimeter attribute. So, the solution is to use the double underscore
naming convention because Python automatically does the
name translation for us. This ensures we use our own
perimeter(), not one
from a derived class, because the dunder,
__, will add the class name.
If this concept interests you, and you would like to hear and see an even better discussion of this topic watch the video.
Published: 07-24-2013 16:20:00