1

I have recently started using classes in Python since I realized how useful they could be, but I'm still beginning to grasp the best practices when designing them.

So when I define my classes, usually I end up defining a lot of attributes in the __init__ method (or other method that initializes them), storing them in self and after that having to load all of them for each other method in which I may want to use them, as in the example that follows:

class MyClass:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
    def foo(self):
        a = self.a
        b = self.b
        c = self.c
        ''' Perform some operations with a, b and c '''

This may look OK with two or three attributes, but when the number of attributes that I need increases (up to 10-20), I feel this practice becomes less clean and a lot of code repeats itself with lines like a = self.a, b = self.b, ... all the time.

Also, the alternative of avoiding the lines like a = self.a and just calling self.a when I need it is not that appealing when there are many attributes, since the code starts getting cluttered with self's everywhere and becomes hard to read. Are there better approaches for this? Would you recommend me to look into some Python topic that I may be missing?

Thank you!

EDIT: to give a practical example where this issue arises: I want to create a class that implement some methods to initialize a neural network, give some default attributes that I usually use, train the network, postprocess it to get specific metrics from the model on different test sets... That is why I might find it useful to access some attributes like number of nodes per layer, number of hidden layers, solver type, regularization, etc.

For instance:

class nn_api:
            
    def init_default(self, w_size, n_hidden):
        self.w_size = w_size
        self.shift = 1
        self.stride = 1
        self.n_neurons = 128
        self.n_hidden = n_hidden
        self.activation = 'elu'
        self.batch_size = 32
        ...
 
    def collect_data(self):
        ...

    def build_model(self):
        ...

    def fit(self):
        ...

    def postprocess(self):
        ...
4
  • 1
    I would call them instance attributes. Commented Mar 9, 2022 at 16:45
  • 2
    The advantage of using self.a everywhere is that this makes it obvious that the reference is an instance attribute. A bare a could be anything. Commented Mar 9, 2022 at 16:46
  • Note that "10-20" attributes is rather excessive and uncommon. A practical example might be useful. Commented Mar 9, 2022 at 16:57
  • Maybe you can use a dictionary? Commented Mar 9, 2022 at 17:42

1 Answer 1

1

I’d say that the fact that the class has so many attributes in itself is something to worry about. It sounds like the class is doing too many things at once. It “knows“ about too many details of your code.

In this case you could try to group your attribtues into separate classes. This means trying to find attributes that always are used together, then moving them into their own class together with the the part of the code that works with them.

This approach is also described here as Code Smell 34.

Sign up to request clarification or add additional context in comments.

2 Comments

@MisterMiyagi: I stand corrected. I’ve edited the above answer to only use the more generic word “attribute”. Seems like my use of terms was not precise after all.
So, if I separate the attributes and the methods that use them in different classes, but I'd still like to have one single class that can perform all those tasks, is it a good idea to then have another class that inherits from all the previous ones?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.