Kent Johnson wrote: > Nigel Rowe wrote: >> I have two modules, both define the same set of classes (with differing >> implementations) and a number of utility functions that use those >> classes. >> >> The utility functions are identical (the differences I need are >> abstracted in the classes), so they are cut'n'pasted into both files. >> >> A simplified concrete example (not what I'm doing, but it illustrates the >> point): >> >> -- C.py -- >> |class Comment: >> | def __init__(self, value): >> | self.value = value >> | >> | def __str__(self): >> | return "/* " + self.value + " */" >> | >> |# utility functions >> |import time >> |def stamp(): >> | return Comment(time.asctime()) >> >> >> -- P.py -- >> |class Comment: >> | def __init__(self, value): >> | self.value = value >> | >> | def __str__(self): >> | return "# " + self.value + "\n" >> | >> |# utility functions >> |import time >> |def stamp(): >> | return Comment(time.asctime()) >> >> >> How can I refactor these modules to avoid the code duplication? > > You could make stamp() a classmethod of a common base class like this: > > # CommentBase.py > import time > > class CommentBase(object): > def stamp(cls): # cls will be one of the Comment implementations > return cls(time.asctime()) > > stamp = classmethod(stamp) > > # C.py > from CommentBase import CommentBase > class Comment(CommentBase): > def __init__(self, value): > self.value = value > > > # Client code > from C import Comment > > c = Comment.stamp() # This becomes CommentBase.stamp(Comment) > print type(c), c.value > > > Kent
Thanks Kent, that's an approach that wouldn't have occurred to me. Unfortunately it's not going to do the job for me, since it would require extensive changes to the client code. ie. import C as lang lang.stamp() would need to be re-written as import C as lang lang.Comment.stamp() The other problem is that there are a LOT of classes, and some of the utility functions make use of multiple classes. eg. (not real code) class this: ... class that: ... class other: ... class something: ... def utl_1(): x = this() y = other() def utl_2(): z = this() foo = something() def utl_3(): a = something() b = other() (You get the idea.) Maybe I'm going too far, trying to eliminate the cut'n'paste, but I've always thought it a bad smell. -- Nigel Rowe A pox upon the spammers that make me write my address like.. rho (snail) swiftdsl (stop) com (stop) au _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor