Redundancy in __init__ in python?

  • Context: Python 
  • Thread starter Thread starter Isaac0427
  • Start date Start date
  • Tags Tags
    Python
Click For Summary

Discussion Overview

The discussion revolves around the redundancy of initializing instance variables in Python classes, particularly focusing on the __init__ method. Participants explore whether it is necessary to explicitly assign parameters to instance variables or if there are alternative approaches that could simplify this process.

Discussion Character

  • Exploratory
  • Technical explanation
  • Debate/contested

Main Points Raised

  • Some participants question the necessity of explicitly assigning parameters to instance variables in the __init__ method, suggesting that it may be redundant.
  • Others argue that there are scenarios, such as different types of vector representations, where the initialization process may vary significantly, thus justifying explicit assignments.
  • A participant proposes a hackish method using self.__dict__.update to automatically assign parameters, but acknowledges that this approach may complicate maintenance.
  • Another participant expresses a preference for using a code generator or library function to reduce boilerplate code, while also recognizing the cognitive load involved in parsing complex updates.
  • Some participants mention the introduction of data classes in Python 3.7 as a more structured way to handle such initializations, which could alleviate some of the concerns about redundancy.

Areas of Agreement / Disagreement

Participants express differing views on the necessity and practicality of explicit assignments in the __init__ method. While some see value in maintaining clarity through explicit assignments, others advocate for alternative methods to reduce boilerplate code. The discussion remains unresolved regarding the best approach to handle this aspect of Python class design.

Contextual Notes

Participants highlight potential limitations in their approaches, including the complexity of maintenance and the cognitive load associated with certain coding practices. The discussion also reflects varying preferences for code style and structure.

Who May Find This Useful

Readers interested in Python programming, particularly those exploring class design, initialization practices, and code optimization techniques, may find this discussion relevant.

Isaac0427
Insights Author
Gold Member
Messages
718
Reaction score
163
TL;DR
I am learning about classes, and something about __init__ seems redundant-- I'm sure there's a reason for it, which is what I am looking for.
Here is an example code in python, describing a class of fruits:
Python:
class Fruits(object):
    def __init__(self, color, taste):
        self.color = color
        self.taste = taste

If, in general, we ALWAYS do this:
Python:
class ExampleClass(object):
    def __init__(self, property1, property2):
        self.property1 = property1
        self.property2 = property2
why don't we just write
Code:
def __init__(self, property1, property2)
instead of adding the self.property1 = property1 etc?

Is there ever a time where we wouldn't follow the "general formula" in this post's second block of code? If not, is there a reason python can't just fill in the rest of the "formula" if given
Code:
def __init__(self, property1, property2)
?

Thank you!
 
Technology news on Phys.org
We don't always do that. You could imagine a class that stores a direction vector and can take initialisation in terms of (x,y,z) or (r,theta,phi):
Python:
class UnitDirectionVector:
    def __init__(self, r1, r2, r3, vectorType):
        if vectorType == "cartesian":
            # Interpret r1,r2,r3 as x,y,z and convert to unit vector
            r = math.sqrt(r1*r1+r2*r2+r3*r3)
            self.x = r1 / r
            self.y = r2 / r
            self.z = r3 / r
        elif vectorType == "polar":
            # Interpret r1,r2,r3 as r,theta,phi and store unit vector
            self.x = math.cos(r3) * math.sin(r2)
            self.y = math.sin(r3) * math.sin(r2)
            self.z = math.cos(r2)
        else:
            raise ValueError("Unrecognised vectorType "+str(vectorType))
That said, it is a common pattern to be just copying the __init__ function arguments into members, at least as part of what __init__ does. There are ways of using python's ability to examine its own code to do just that (Google lead me here), but the general feeling seems to be that it's overly complex for something straightforward. Do you really want python to re-examine a function's argument list every time you create an object, just to save you a bit of typing? That would potentially be rather slow, possibly critically so if the object is being created in a loop.

Now, if someone could write a macro for my code editor that parses my __init__() definition and auto-generates the self.param1 = param1 statements for me, that would be great.
 
Last edited:
  • Like
Likes   Reactions: Isaac0427
Ibix said:
if someone could write a macro for my code editor that parses my __init__() definition and auto-generates the self.param1 = param1 statements for me, that would be great.

There's a somewhat hackish way to do this:

Python:
class Test:
    def __init__(self, a, b, c):
        self.__dict__.update((k, v) for k, v in locals().items() if k != 'self')

test = Test("a", "b", "c")
print(test.a)  # prints a
print(test.b)  # prints b
print(test.c)  # prints c
print(test.__dict__)  #  {'a': 'a', 'b': 'b', 'c': 'c'}
 
PeterDonis said:
There's a somewhat hackish way to do this:

Python:
class Test:
    def __init__(self, a, b, c):
        self.__dict__.update((k, v) for k, v in locals().items() if k != 'self')

test = Test("a", "b", "c")
print(test.a)  # prints a
print(test.b)  # prints b
print(test.c)  # prints c
print(test.__dict__)  #  {'a': 'a', 'b': 'b', 'c': 'c'}
That's related to one of the suggestions in the page I linked, which did self.__dict__.update(kwargs). The comments seemed to be along the lines of "think of the poor guy who has to maintain this". I was thinking more of a code generator in the editor that, given def __init__(self,a,b,c):, would generate
Python:
        self.a=a
        self.b=b
        self.c=c
 
Ibix said:
The comments seemed to be along the lines of "think of the poor guy who has to maintain this".

I agree that just having def __init__(self, **kwargs) is not good. That's why I explicitly specified the arguments to __init__ and did the dictionary update excluding self.

Ibix said:
I was thinking more of a code generator in the editor

My general attitude towards code generators is that I would rather write a library function or use some other general feature of the language so that I don't have to write boilerplate code at all. I am probably an outlier in this respect. :wink:
 
PeterDonis said:
My general attitude towards code generators is that I would rather write a library function or use some other general feature of the language so that I don't have to write boilerplate code at all. I am probably an outlier in this respect. :wink:
I've done both. For something like copying a half dozen parameters into members I'd prefer the boilerplate just to save the cognitive load involved in parsing your update() call. On the other hand I've seen code that calculated the mean values of each one of eighty columns in a dataset by summing each one, counting it, and dividing the two, with eighty cut-and-paste copies. I ended up writing a new program to analyse the original program in order to convince myself that every variable had gone through the same process. That got replaced with smarter code.
 
Ibix said:
For something like copying a half dozen parameters into members I'd prefer the boilerplate just to save the cognitive load involved in parsing your update() call.

Python now (as of 3.7) has data classes, which are a less hacky way of doing what I did and can also help to reduce the cognitive load involved:

https://www.python.org/dev/peps/pep-0557/
 
Ibix said:
Now, if someone could write a macro for my code editor that parses my __init__() definition and auto-generates the self.param1 = param1 statements for me, that would be great.
Which editor are you using?
 

Similar threads

Replies
13
Views
2K
  • · Replies 23 ·
Replies
23
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 43 ·
2
Replies
43
Views
4K
  • · Replies 2 ·
Replies
2
Views
1K
  • · Replies 9 ·
Replies
9
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 2 ·
Replies
2
Views
4K