'Demonstrate effective use of super()'
import collections
import logging
logging.basicConfig(level='INFO')
class LoggingDict(dict):
# Simple example of extending a builtin class
def __setitem__(self, key, value):
logging.info('Setting %r to %r' % (key, value))
return super(LoggingDict, self).__setitem__(key, value)
class LoggingOD(LoggingDict, collections.OrderedDict):
# Build new functionality by reordering the MRO
pass
ld = LoggingDict([('red', 1), ('green', 2), ('blue', 3)])
print ld
ld['red'] = 10
ld = LoggingOD([('red', 1), ('green', 2), ('blue', 3)])
print ld
ld['red'] = 10
print '-' * 20
# ------- Show the order that the methods are called ----------
def show_call_order(cls, methname):
'Utility to show the call chain'
classes = [cls for cls in cls.__mro__ if methname in cls.__dict__]
print ' ==> '.join('%s.%s' % (cls.__name__, methname) for cls in classes)
show_call_order(LoggingOD, '__setitem__')
show_call_order(LoggingOD, '__iter__')
print '-' * 20
# ------- Validate and document any call order requirements -----
position = LoggingOD.__mro__.index
assert position(LoggingDict) < position(collections.OrderedDict)
assert position(collections.OrderedDict) < position
# ------- Getting the argument signatures to match --------------
class Shape(object):
def __init__(self, shapename, **kwds):
self.shapename = shapename
super(Shape, self).__init__(**kwds)
class ColoredShape(Shape):
def __init__(self, color, **kwds):
self.color = color
super(ColoredShape, self).__init__(**kwds)
cs = ColoredShape(color='red', shapename='circle')
# -------- Making sure a root exists ----------------------------
class Root(object):
def draw(self):
try:
super(Root, self).draw # check for masked draw() methods
except AttributeError:
pass # the delegation chain stops here
else:
raise Exception('Root.draw() not last in __mro__')
class Shape(Root):
def __init__(self, shapename, **kwds):
self.shapename = shapename
super(Shape, self).__init__(**kwds)
def draw(self):
print 'Drawing. Setting shape to:', self.shapename
super(Shape, self).draw()
class ColoredShape(Shape):
def __init__(self, color, **kwds):
self.color = color
super(ColoredShape, self).__init__(**kwds)
def draw(self):
print 'Drawing. Setting color to:', self.color
super(ColoredShape, self).draw()
ColoredShape(color='blue', shapename='square').draw()
print '-' * 20
# ------- Show how to incorporate a non-cooperative class --------
class Moveable(object):
# non-cooperative class that doesn't use super()
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self):
print 'Drawing at position:', self.x, self.y
class MoveableAdapter(Root):
# make a cooperative adapter class for Moveable
def __init__(self, x, y, **kwds):
self.moveable = Moveable(x, y)
super(MoveableAdapter, self).__init__(**kwds)
def draw(self):
self.moveable.draw()
super(MoveableAdapter, self).draw()
class MovableColoredShape(ColoredShape, MoveableAdapter):
pass
MovableColoredShape(color='red', shapename='triangle', x=10, y=20).draw()
# -------- Complete example ------------------------------------
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
oc = OrderedCounter('abracadabra')
print oc
Diff to Previous Revision
--- revision 4 2011-05-31 06:24:39
+++ revision 5 2011-06-01 01:41:21
@@ -22,10 +22,9 @@
ld = LoggingOD([('red', 1), ('green', 2), ('blue', 3)])
print ld
ld['red'] = 10
-
print '-' * 20
-# ------- Show the order that the methods are called -------
+# ------- Show the order that the methods are called ----------
def show_call_order(cls, methname):
'Utility to show the call chain'
@@ -34,8 +33,15 @@
show_call_order(LoggingOD, '__setitem__')
show_call_order(LoggingOD, '__iter__')
+print '-' * 20
-# ------- Getting the argument signatures to match ----------
+# ------- Validate and document any call order requirements -----
+
+position = LoggingOD.__mro__.index
+assert position(LoggingDict) < position(collections.OrderedDict)
+assert position(collections.OrderedDict) < position
+
+# ------- Getting the argument signatures to match --------------
class Shape(object):
def __init__(self, shapename, **kwds):
@@ -49,11 +55,16 @@
cs = ColoredShape(color='red', shapename='circle')
-# -------- Making sure a root exists --------------------------
+# -------- Making sure a root exists ----------------------------
class Root(object):
def draw(self):
- pass # the delegation chain stops here
+ try:
+ super(Root, self).draw # check for masked draw() methods
+ except AttributeError:
+ pass # the delegation chain stops here
+ else:
+ raise Exception('Root.draw() not last in __mro__')
class Shape(Root):
def __init__(self, shapename, **kwds):
@@ -72,8 +83,9 @@
super(ColoredShape, self).draw()
ColoredShape(color='blue', shapename='square').draw()
+print '-' * 20
-# ------- Show how to wrap a non-cooperative class --------
+# ------- Show how to incorporate a non-cooperative class --------
class Moveable(object):
# non-cooperative class that doesn't use super()
@@ -97,7 +109,7 @@
MovableColoredShape(color='red', shapename='triangle', x=10, y=20).draw()
-# -------- Complete example ---------------------------------
+# -------- Complete example ------------------------------------
from collections import Counter, OrderedDict