4

In Python, I can declare attributes all over the class. For example :

class Foo:
def __init__(self):
    self.a = 0

def foo(self):
    self.b = 0

It's difficult to retrieve all attributes in my class when I have a big class with a lot of attributes.

Is it better to have the following code (a) or the next following code (b) :

a) Here, it's difficult to locate all attributes :

class Foo:
    def __init__(self):
        foo_1()
        foo_2()

    def foo_1(self):
        self.a = 0
        self.b = 0

    def foo_2(self):
        self.c = 0

b) Here, it's easy to locate all attributes but is it beautiful ?

class Foo:
    def __init__(self):
        (self.a, self.b) = foo_1()
        self.c = foo_2()

    def foo_1(self):
        a = 0
        b = 0
        return (a, b)

    def foo_2(self):
        c = 0
        return c

In a nutshell, what is your conventions to declare your attributes in a class ?

EDIT:

Of course, it's a simple example and there's no need to improve my code here. Just imagine a complex class with a lot of "small methods" (to divide my code, to improve the readability) called in _init_().

Sandro Munda
  • 39,921
  • 24
  • 98
  • 123

4 Answers4

5

Ideally, your constructor should not call methods: a constructor should not do real work.

If the number of attributes grows out of proportion, you should refactor your class, for example using Extract Class to break your class into several classes, thereby respecting the single responsibility principle.

Tommy
  • 1,219
  • 11
  • 18
4

What's wrong with this:

class Foo:
    def __init__(self):
        self.a = 0
        self.b = 1
        self.c = 2

Or if a, b and c are related in some way, you can declare them on a single line:

class Foo:
    def __init__(self):
        self.a, self.b, self.c = 0, 1, 2

Or if a, b and c are related in some way and you're initialising them to the same immutable value, you can declare them in a single assignment:

class Foo:
    def __init__(self):
        self.a = self.b = self.c = 0
moinudin
  • 134,091
  • 45
  • 190
  • 216
  • Agreed. (Nitpicking: In this particular example, you could do `self.a = self.b = self.c = 0` - assignments aren't expressions, but this special case is allowed; of course this is rarely useful and has different semantics when assigning a mutable object). –  Dec 30 '10 at 10:49
  • If my method \__init\__ needs to do much of anything, I prefer to divide \__init\__ into several small methods. In this case, is it better to declare attributes only in \__init\__ (see a) ) or declare attributes directly in the small methods (see b) ) – Sandro Munda Dec 30 '10 at 10:50
  • @SeyZ: As much as I dislike large methods, if init becomes this larger, your class is propably to large itself (see single responsibility principle). How large do we talk about? If you want to structure a handful of initializations, put blank lines in between and perhaps a comment for the whole paragraph. –  Dec 30 '10 at 10:53
  • @delnan Ok I see, so it's better to have some "paragraphs" (with a comment above) than calling a "private" (arrounded by quotes :]) method to do what I have to do ? – Sandro Munda Dec 30 '10 at 10:56
  • @SeyZ: I'd say so, yes. Adding a method for it just adds extra lines and weight (and the danger that some fool calls it and partially reinitializes the object), with at most minimal readability bonus. If you need that bit of readability so much because there's a hundred things to be done in `__init__`, your class is propably too large anyway. –  Dec 30 '10 at 11:00
0

First of all, you are not talking about class attributes here, but instance attributes. My convention for that is to but all of them in the constructor, with the value of None if they are initialized in another method. That way I can always tell what to expect. It's sort of like declaring them, even though it isn't mandatory.

e.g.:

class Foo(object):
    def __init__(self, a=None, b=None, c=None):
        self.a = a
        self.b = b
        self.c = c

Well, I also like to make inititializers as keyword arguments, it makes it more flexible. I can easily override the defaults that way as well.

Keith
  • 42,110
  • 11
  • 57
  • 76
0

In Python, I can declare attributes all over the class.

Correct.

It's difficult to retrieve all attributes in my class when I have a big class with a lot of attributes.

Nope. dir(object) or obj.__dict__ are helpful there. And besides, why would you want to retrieve all the attributes?

Here, it's difficult to locate all attributes

A good editor/IDE can help you find the definition. I use WingIDE for this, it's pretty good.

Here, it's easy to locate all attributes but is it beautiful ?

Well, this particular code, maybe not, but it is quite common to declare all public attributes in __init__ or in the class (but beware the Jabberwock when you do this). That way you know they are available, which is good.

Community
  • 1
  • 1
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251