While writing the constructor for class A in Python, I calculate some of the class's fields using function fun(). This function is never used outside the constructor of instances of this class. In situations like these, I tend to write fun() so that it returns the desired values and then I assign these values in the initialization, like so:

class A:
    def __init__(self):
        self.x, self.y = self.fun(2)

    def fun(self, i: int) -> tuple[int, int]:
        return i**2, i**3

This to me seems clear in that the constructor clearly shows which fields are created.

A different approach would have these fields be assigned to inside fun(), like so:

class A:
    def __init__(self):

    def fun(self, i: int):
        self.a = i**2
        self.b = i**3

I feel like this second method hinders readability because to see what fields are created or assigned to, I have to inspect fun(). However, maybe I'm missing something.

Is there any reason to prefer the second method over the first? Or are there any more reasons to prefer method one other than readability?

This question occurred to me while writing Python, but is not restricted to the Python language.


1 Answer 1

    def __init__(self):
        self.x, self.y = fun(2)

Yes, I agree with you. Prefer that style.

Why? The __init__ ctor should offer the Gentle Reader a convenient summary of the public and _private attributes that affect the object's behavior. You are exactly right that asking a maintenance engineer to peruse diverse methods beyond __init__ to understand what attributes might be defined over an object's lifetime is unreasonable. It will impact maintainability.

Additionally, breaking out complex logic as you did is good for readability of the constructor, and good for anyone who wants to write small unit tests. I would only amend it to def _fun, indicating it is private.

Conventionally we use a placeholder value of None if we're not quite ready to immediately find a "real" value.

  • If the goal is readability, suggest putting self.y on a second line
    – Adam B
    Sep 21, 2023 at 19:37
  • @AdamB, I disagree. Returning a tuple makes perfect sense, and an a, b, c = ... tuple unpack is the pythonic way to approach it. The alternative would be to insist that a helper return just a single scalar, which in some contexts would harm rather than help readability. // In the many projects that choose to adopt black, insisting on the multi-line expression that you suggest would be a non-starter.
    – J_H
    Sep 21, 2023 at 23:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.