#!/usr/bin/env python
from abc import ABCMeta, abstractmethod
def subclasshook( required) :
"""Generates a subclass hook based on a simple check for attributes."""
def __subclasshook__( cls, Check) :
rtn = True
for r in required:
if not any ( r in vars ( BaseClass) for BaseClass in Check.__mro__) :
rtn = NotImplemented
return rtn
return __subclasshook__
class Duck( object ) :
def __init__ ( self , fly, quack) :
self ._fly_behaviour = fly
self ._quack_behaviour = quack
def fly( self ) :
return self ._fly_behaviour.fly ( )
def quack( self ) :
return self ._quack_behaviour.quack ( )
def swim( self ) :
print "All ducks float, even decoys!"
class MallardDuck( Duck) :
def __init__ ( self ) :
Duck.__init__ ( self , Fly( ) , Quack( ) )
print "I'm a real Mallard Duck"
class ModelDuck( Duck) :
def __init__ ( self ) :
Duck.__init__ ( self , FlyNoWay( ) , SqueakQuack( ) )
print "I'm a Model Duck"
class DecoyDuck( Duck) :
def __init__ ( self ) :
Duck.__init__ ( self , FlyNoWay( ) , MuteQuack( ) )
print "I'm a Decoy Duck"
class FlyBehavior:
__metaclass__ = ABCMeta
@ abstractmethod
def fly( self ) :
pass
__subclasshook__ = classmethod ( subclasshook( [ "fly" ] ) )
class Fly( FlyBehavior) :
def fly( self ) :
print "I'm flying!!"
class FlyNoWay( FlyBehavior) :
def fly( self ) :
print "I can't fly"
class FlyRocketPowered( FlyBehavior) :
def fly( self ) :
print "I'm flying with a rocket!"
class QuackBehavior:
__metaclass__ = ABCMeta
@ abstractmethod
def quack( self ) :
pass
__subclasshook__ = classmethod ( subclasshook( [ "quack" ] ) )
class Quack( QuackBehavior) :
def quack( self ) :
print "Quack"
class MuteQuack( QuackBehavior) :
def quack( self ) :
print "<< Silence >>"
class SqueakQuack( QuackBehavior) :
def quack( self ) :
print "Squeak"
if __name__ == "__main__" :
print '#' *80
print "Mallard Duck"
print '#' *80
mallard = MallardDuck( )
mallard.quack ( )
mallard.fly ( )
print '#' *80
print "Model Duck"
print '#' *80
model = ModelDuck( )
model.fly ( )
model._fly_behaviour = FlyRocketPowered( )
model.fly ( )
print '#' *80
print "Decoy Duck"
print '#' *80
decoy = DecoyDuck( )
decoy.fly ( )
decoy.quack ( )
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uCgpmcm9tIGFiYyBpbXBvcnQgQUJDTWV0YSwgYWJzdHJhY3RtZXRob2QKCmRlZiBzdWJjbGFzc2hvb2socmVxdWlyZWQpOgogICAgIiIiR2VuZXJhdGVzIGEgc3ViY2xhc3MgaG9vayBiYXNlZCBvbiBhIHNpbXBsZSBjaGVjayBmb3IgYXR0cmlidXRlcy4iIiIKICAgIGRlZiBfX3N1YmNsYXNzaG9va19fKGNscywgQ2hlY2spOgogICAgICAgIHJ0biA9IFRydWUKICAgICAgICBmb3IgciBpbiByZXF1aXJlZDoKICAgICAgICAgICAgaWYgbm90IGFueShyIGluIHZhcnMoQmFzZUNsYXNzKSBmb3IgQmFzZUNsYXNzIGluIENoZWNrLl9fbXJvX18pOgogICAgICAgICAgICAgICAgcnRuID0gTm90SW1wbGVtZW50ZWQKICAgICAgICByZXR1cm4gcnRuCiAgICByZXR1cm4gX19zdWJjbGFzc2hvb2tfXwoKY2xhc3MgRHVjayhvYmplY3QpOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGZseSwgcXVhY2spOgogICAgICAgIHNlbGYuX2ZseV9iZWhhdmlvdXIgPSBmbHkKICAgICAgICBzZWxmLl9xdWFja19iZWhhdmlvdXIgPSBxdWFjawoKICAgIGRlZiBmbHkoc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2ZseV9iZWhhdmlvdXIuZmx5KCkKCiAgICBkZWYgcXVhY2soc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX3F1YWNrX2JlaGF2aW91ci5xdWFjaygpCgogICAgZGVmIHN3aW0oc2VsZik6CiAgICAgICAgcHJpbnQgIkFsbCBkdWNrcyBmbG9hdCwgZXZlbiBkZWNveXMhIgoKY2xhc3MgTWFsbGFyZER1Y2soRHVjayk6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgRHVjay5fX2luaXRfXyhzZWxmLCBGbHkoKSwgUXVhY2soKSkKICAgICAgICBwcmludCAiSSdtIGEgcmVhbCBNYWxsYXJkIER1Y2siCgpjbGFzcyBNb2RlbER1Y2soRHVjayk6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgRHVjay5fX2luaXRfXyhzZWxmLCBGbHlOb1dheSgpLCBTcXVlYWtRdWFjaygpKQogICAgICAgIHByaW50ICJJJ20gYSBNb2RlbCBEdWNrIgoKY2xhc3MgRGVjb3lEdWNrKER1Y2spOgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIER1Y2suX19pbml0X18oc2VsZiwgRmx5Tm9XYXkoKSwgTXV0ZVF1YWNrKCkpCiAgICAgICAgcHJpbnQgIkknbSBhIERlY295IER1Y2siCgpjbGFzcyBGbHlCZWhhdmlvcjoKICAgIF9fbWV0YWNsYXNzX18gPSBBQkNNZXRhCgogICAgQGFic3RyYWN0bWV0aG9kCiAgICBkZWYgZmx5KHNlbGYpOgogICAgICAgIHBhc3MKCiAgICBfX3N1YmNsYXNzaG9va19fID0gY2xhc3NtZXRob2Qoc3ViY2xhc3Nob29rKFsiZmx5Il0pKQoKY2xhc3MgRmx5KEZseUJlaGF2aW9yKToKICAgIGRlZiBmbHkoc2VsZik6CiAgICAgICAgcHJpbnQgIkknbSBmbHlpbmchISIKCmNsYXNzIEZseU5vV2F5KEZseUJlaGF2aW9yKToKICAgIGRlZiBmbHkoc2VsZik6CiAgICAgICAgcHJpbnQgIkkgY2FuJ3QgZmx5IgoKY2xhc3MgRmx5Um9ja2V0UG93ZXJlZChGbHlCZWhhdmlvcik6CiAgICBkZWYgZmx5KHNlbGYpOgogICAgICAgIHByaW50ICJJJ20gZmx5aW5nIHdpdGggYSByb2NrZXQhIgoKY2xhc3MgUXVhY2tCZWhhdmlvcjoKICAgIF9fbWV0YWNsYXNzX18gPSBBQkNNZXRhCgogICAgQGFic3RyYWN0bWV0aG9kCiAgICBkZWYgcXVhY2soc2VsZik6CiAgICAgICAgcGFzcwoKICAgIF9fc3ViY2xhc3Nob29rX18gPSBjbGFzc21ldGhvZChzdWJjbGFzc2hvb2soWyJxdWFjayJdKSkKCmNsYXNzIFF1YWNrKFF1YWNrQmVoYXZpb3IpOgogICAgZGVmIHF1YWNrKHNlbGYpOgogICAgICAgIHByaW50ICJRdWFjayIKCmNsYXNzIE11dGVRdWFjayhRdWFja0JlaGF2aW9yKToKICAgIGRlZiBxdWFjayhzZWxmKToKICAgICAgICBwcmludCAiPDwgU2lsZW5jZSA+PiIKCmNsYXNzIFNxdWVha1F1YWNrKFF1YWNrQmVoYXZpb3IpOgogICAgZGVmIHF1YWNrKHNlbGYpOgogICAgICAgIHByaW50ICJTcXVlYWsiCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgoKICAgIHByaW50ICcjJyo4MAogICAgcHJpbnQgIk1hbGxhcmQgRHVjayIKICAgIHByaW50ICcjJyo4MAogICAgbWFsbGFyZCA9IE1hbGxhcmREdWNrKCkKICAgIG1hbGxhcmQucXVhY2soKQogICAgbWFsbGFyZC5mbHkoKQoKICAgIHByaW50ICcjJyo4MAogICAgcHJpbnQgIk1vZGVsIER1Y2siCiAgICBwcmludCAnIycqODAKICAgIG1vZGVsID0gTW9kZWxEdWNrKCkKICAgIG1vZGVsLmZseSgpCiAgICBtb2RlbC5fZmx5X2JlaGF2aW91ciA9IEZseVJvY2tldFBvd2VyZWQoKQogICAgbW9kZWwuZmx5KCkKCiAgICBwcmludCAnIycqODAKICAgIHByaW50ICJEZWNveSBEdWNrIgogICAgcHJpbnQgJyMnKjgwCiAgICBkZWNveSA9IERlY295RHVjaygpCiAgICBkZWNveS5mbHkoKQogICAgZGVjb3kucXVhY2soKQ==