How to reduce the DRY violation in this code

Steve D'Aprano steve+python at pearwood.info
Tue Sep 27 11:49:56 EDT 2016


I have a class that takes a bunch of optional arguments. They're all
optional, with default values of various types. For simplicity, let's say
some are ints and some are floats:


class Spam:
    def __init__(self, bashful=10.0, doc=20.0, dopey=30.0, 
                 grumpy=40, happy=50, sleepy=60, sneezy=70):
        # the usual assign arguments to attributes dance...
        self.bashful = bashful
        self.doc = doc
        # etc.


I also have an alternative constructor that will be called with string
arguments. It converts the strings to the appropriate type, then calls the
real constructor, which calls __init__. Again, I want the arguments to be
optional, which means providing default values:


    @classmethod
    def from_strings(cls, bashful='10.0', doc='20.0', dopey='30.0', 
                     grumpy='40', happy='50', sleepy='60', sneezy='70'):
        bashful = float(bashful)
        doc = float(doc)
        dopey = float(dopey)
        grumpy = int(grumpy)
        happy = int(happy)
        sleepy = int(sleepy)
        sneezy = int(sneezy)
        return cls(bashful, doc, dopey, grumpy, happy, sleepy, sneezy)


That's a pretty ugly DRY violation. Imagine that I change the default value
for bashful from 10.0 to (let's say) 99. I have to touch the code in three
places (to say nothing of unit tests):

- modify the default value in __init__
- modify the stringified default value in from_strings
- change the conversion function from float to int in from_strings


Not to mention that each parameter is named seven times.


How can I improve this code to reduce the number of times I have to repeat
myself?





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list