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!
CodePudding user response:
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.
CodePudding user response:
i would say that you need some deep dive in this topic from David Beazley :
https://files.speakerdeck.com/presentations/ef67f91a7cd64f139f571a8d0884eb15/Py3Meta.pdf
Good luck :)
For wetting your apetite :
class Structure:
_fields = []
def __init__(self, *args):
if len(args) != self._fields:
raise TypeError('Wrong # args')
for name, val in zip(self._fields, args):
setattr(self, name, val)
class Stock(Structure):
_fields = ['name', 'shares', 'price']
also from this presentation ...