[EMAIL PROTECTED] writes: > Suppose you're writing a class "Rational" for rational numbers. The > __init__ function of such a class has two quite different roles to > play.
That should be your first clue to question whether you're actually needing separate functions, rather than trying to force one function to do many different things. > First, it's supposed to allow users of the class to create Rational > instances; in this role, __init__ is quite a complex beast. The __init__ function isn't the "constructor" you find in other languages. Its only purpose is to initialise an already-created instance, not make a new one. > It needs to allow arguments of various types---a pair of integers, a > single integer, another Rational instance, and perhaps floats, Decimal > instances, and suitably formatted strings. It has to validate the > input and/or make sure that suitable exceptions are raised on invalid > input. And when initializing from a pair of integers---a numerator > and denominator---it makes sense to normalize: divide both the > numerator and denominator by their greatest common divisor and make > sure that the denominator is positive. All of this points to having a separate constructor function for each of the inputs you want to handle. > But __init__ also plays another role: it's going to be used by the > other Rational arithmetic methods, like __add__ and __mul__, to > return new Rational instances. No, it won't; those methods won't "use" the __init__ method. They will use a constructor, and __init__ is not a constructor (though it does get *called by* the construction process). > For this use, there's essentially no need for any of the above > complications: it's easy and natural to arrange that the input to > __init__ is always a valid, normalized pair of integers. Therefore, make your __init__ handle just the default, natural case you identify. class Rational(object): def __init__(self, numerator, denominator): self.numerator = numerator self.denominator = denominator > So the question is: (how) do people reconcile these two quite > different needs in one function? By avoiding the tendency to crowd a single function with disparate functionality. Every function should do one narrowly-defined task and no more. @classmethod def from_string(input): (n, d) = parse_elements_of_string_input(input) return Rational(n, d) @classmethod def from_int(input): return Rational(input, 1) @classmethod def from_rational(input): (n, d) = (input.numerator, input.denominator) return Rational(n, d) def __add__(self, other): result = perform_addition(self, other) return result def __sub__(self, other): result = perform_subtraction(self, other) return result Put whatever you need to for 'parse_elements_of_string_input', 'perform_addition', 'perform_subtraction', etc; either the calculation itself, if simple, or a call to a function that can contain the complexity. Use Python's exception system to avoid error-checking all over the place; if there's a problem with the subtraction, for instance, let the exception propagate up to the code that gave bad input. The alternate constructors are decorated as '@classmethod' since they won't be called as instance methods, but rather: foo = Rational.from_string("355/113") bar = Rational.from_int(17) baz = Rational.from_rational(foo) -- \ "If you can't beat them, arrange to have them beaten." -- | `\ George Carlin | _o__) | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list