4

This may be a stupid / trivial question, but I'm confused in this matter.

What is the encouraged (pythonic) way of declaring instance fields - in the constructor, or in the class body itself?

class Foo:
    """ Foo class """

    # While we are at it, how to properly document the fields?
    bar = None

    def __init__(self, baz):
        """ Make a Foo """

        self.bar = baz

OR:

class Foo:
    """ Foo class """

    def __init__(self, baz):
        """ Make a Foo """

        self.bar = baz
4
  • 3
    i think second is better Commented Aug 7, 2014 at 6:53
  • Documentation: I simply write """bar initial value""" below the field. Commented Aug 7, 2014 at 6:54
  • 1
    To me, the first reads like a class attribute rather than an instance attribute (stackoverflow.com/questions/207000/…). One day you'll forget to assign to bar in __init__() and inadvertently end up with a class attribute (and a hard-to-find bug). For these reasons, I'd use #2 every day of the week. Commented Aug 7, 2014 at 7:02
  • @NPE If a method sets it as self.foo = 123, does that override the "class attribute" effect and make it an instance attribute? Because if so, then I'm fine with this - the class attribute will just hold a never-changed default value. Commented Aug 7, 2014 at 7:04

2 Answers 2

7

It's a matter of expectations. People reading your code will expect that the attributes defined at the top level of the class will be class attributes. The fact that you then always replace them in __init__ will only create confusion.

For that reason you should go with option 2, defining instance attributes inside __init__.

In terms of documenting the attributes, pick a docstring style and stick to it; I like Google's, other options include numpy's.

class Foo:
    """A class for foo-ing bazs. 

    Args:
      baz: the baz to foo

    Attributes:
      bar: we keep the baz around 

    """

    def __init__(self, baz):
        self.bar = baz
Sign up to request clarification or add additional context in comments.

1 Comment

I like the Google's method, it's much more readable. Guess I'll convert my project to this.
3

To keep it simple, let us define class Foo with a class variable bar:

In [34]: class Foo: bar = 1

Now, observe:

In [35]: a = Foo()

In [36]: a.bar
Out[36]: 1

In [37]: Foo.bar = 2

In [38]: a.bar
Out[38]: 2

A change to Foo.bar affects existing instances of the class.

For this reason, one generally avoids class variables, as opposed to instance variables unless one wants these side-effects.

3 Comments

I see where you are coming from. However, in the first example, exactly as it's written, bar is not shared by instances of Foo.
So is this claim true or false? I totally do not want anything to be shared.
@MightyPork I have added an example to demonstrate. NPE is right that my example is not exactly your code. However, I do think it goes to the more general question that you were asking.

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.