Search code examples
pythonclassmember-variables

Where is the recommended way to put member variables when designing classes in python?


I am trying to get familiar with classes in python. In C++ the structure of a class seems straightforward to me, regarding the member variables. You just declare them at the beginning of the class scope or at the end (as public or private, as desired) and work with them as you need.

How is this handled in python?

Right now I tend to write the class and declare the variable where needed:

class Foo():
    standard = "standard"
    def __init__(self, arg_1, arg_2):
        self.first = arg_1
        self.second = self.do_something(arg_2)

    def do_something(param):
        second = # do something with self.standard and param and store it.
        return second 

    def do_another_thing():
        self.third = # do another thing.

I know, that a class can be defined too without member variables and they can be added dynamically.

class Foo():
    pass

foo = Foo()
foo.a = "a"
# etc.

Throwing all of this together it confuses me, since the code becomes harder to read.

So my question is, what is the recommended way to design a class, regarding member variables in python?


Edit:

The way I asked was misleading. Sorry about that! The answers helped me to understand other things, though. ;-)

I'll rephrase: I am not asking for how to solve my confusion regarding variables defined inside the class and variables added dynamically while coding.

What I wanted to solve was my confusion about the design of a python class, regarding member variables. I mean, where to put them the best, to allow a potential reader of the code to see everything without having to search for them. That's why I mentioned classes in C++. You have one place for all member variables and if you want to know which data is stored in the class you look at the beginning or the end of a class, and you get all the information you need.

In the example I wrote above, you see, standard is above __init__(self, ...), first and second are inside of __init(self,...) and third is inside do_something(), which if the class is big could be below all other methods. So you would have to search for it line by line, or never realise it existed.

I hope my question is better proposed now. :-)


Solution

  • All of these approaches work, so it's a matter of your own code standards and documentation.

    Personally, I regard it as good practice to initialise the "public" member attributes in the __init__ function. That makes it obvious what they are, and this should be emphasised by documenting them in the class docstring.

    You still can add variables dynamically throughout the code, but I prefer to only use this where the variables are not expected to be accessed outside the class itself (I usually use a single initial underscore - self._foo to indicate this).

    Assigning properties outside the class completely also has a use case, but for me this is strictly for the convenience of the code that's using that class instance, rather than the class code itself. For example, in Django I quite frequently set custom attributes in the request object, since I know that will be passed around and I can therefore access those attributes elsewhere in the code. However, there is no expectation that the object itself is aware of that extra baggage.