On Wed, 28 Sep 2016 01:49:56 +1000, Steve D'Aprano wrote: > 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): > This is often refered to as using "Magic Numbers" and can be avoided by using constants
HAPPY='50' SNEEZY='70' <snip> def spam: def __init__(self,happy=HAPPY,sneezy=SNEEZY,...) of course Python does not have true constants (hence following the PEP 8 recommendation of making them all caps) so you have to behave yourself regarding their usage. at least now they only need to be changed in 1 location. that said when I find i have situations like this it is often a good idea to re-investigate my approach to the overall problem to see if there is another way to implement it. -- "Humor is a drug which it's the fashion to abuse." -- William Gilbert -- https://mail.python.org/mailman/listinfo/python-list