Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Private" arguments to __init__()?

Tags:

python

I have a class that takes a single parameter a on instantiation, which is stored in the _a attribute. For a number of methods (operators), I need to set also a _b attribute on the result. This is currently implemented in a straight-forward way:

class SomeClass(object):
    def __init__(self, a=0):
        self._a = a
        self._b = 0

    def __add__(self, other):
        result = self.__class__()
        result._b = self._a + other._a
        return result

Now, I have an number of members like _b, such as _c and _d, so __add__ will need an extra line for each of these attributes. Being able to pass these on object instantiation would result in cleaner code:

class SomeClass(object):
    def __init__(self, a=0, _b=0):
        self._a = a
        self._b = 0

    def __add__(self, other):
        return self.__class__(_b=self._a + other._a)

However, I don't want the user to pass values for all of the parameters, except for a as _b, _c and _d are implementation specifics. I could simply state in the docstring not to pass more than one argument. Preceding the 'private' attributes with an underscore is intended to reflect this.

Alternatively, I can try to make it harder for the user to misbehave, by providing a second, private constructor:

class SomeClass(object):
    def __init__(self, a=0):
        self._a = a
        self._init()

    def _init(self, _b=0):
        self._b = _b

    @classmethod
    def _constructor(cls, a, _b):
        obj = cls(a)
        obj._init(b)
        return obj

    def __add__(self, other):
        return self.__class__._constructor(_b=self._a + other._a)

I'm thinking this is a rather clunky solution.

What would be the preferred way to solve this problem? Are there other, more elegant, solutions? Is this really a problem; should I just use the first option and end up with some more lines of code?

like image 373
Brecht Machiels Avatar asked Jan 06 '13 11:01

Brecht Machiels


1 Answers

The _ underscore convention is clear and prevalent through the python world.

You document your 'public' attributes, and just use default arguments with underscores to your __init__ method. Keep it simple.

If someone wants to screw up a class by using those private parameters anyway, you are not going to stop them, not in Python.

like image 186
Martijn Pieters Avatar answered Oct 04 '22 14:10

Martijn Pieters