Edd Barrett
Edd Barrett

Reputation: 3573

Per-class constants in Python

Another Python code style question.

If I have some "constant values" (quoted because there is not such thing in Python) that apply to a single class, what is preferred: module-level variables, or class variables?

E.g. Suppose we have a class Counter which does something when a constant threshold value is reached, which is preferred?

class Counter(object):
    THRESHOLD = 6
    ...

    def increment(self):
        self.val += 1
        if self.val == Counter.THRESHOLD:
            do_something()

or:

COUNTER_THRESHOLD = 6

class Counter(object):
    ...
    def increment(self):
        self.val += 1
        if self.val == COUNTER_THRESHOLD:
            do_something()

The only thing I've managed to dig up is from the Python docs. They suggest that class variables are ideally treated as "constant":

Class variables can be used as defaults for instance variables, but using mutable values there can lead to unexpected results.

https://docs.python.org/2/reference/compound_stmts.html#class-definitions

However, this doesn't really answer the question. EDIT: As @JBernardo pointed out, this is irrelevant, as it refers to mutable data types, not to mutable variable values.

Thoughts?

Thanks

Upvotes: 20

Views: 19640

Answers (2)

SuperBiasedMan
SuperBiasedMan

Reputation: 9969

Definitely keeping it as a member of the class, it's clearer and tidier.

You can have multiple classes each with a threshold that you don't interfere with (not to mention global namespace references to a threshold). It's a lot clearer to read classname.THRESHOLD as that signals an actual meaning to the intent.

But also, it's much better for imports. If you use

from file import classname

You will only keep the threshold if it's actually in the class's namespace, whereas global namespace variables are ignored when importing specific classes/functions.

To demonstrate:

Classy.py

glob = "global"

class ClassName:
    name = "Class Name"

Otherfile.py

from classy import ClassName

print ClassName.name
print glob

Result of running Otherfile.py

Class Name

Traceback (most recent call last):
  File "C:\Users\person\Desktop\otherfile.py", line 4, in <module>
    print glob
NameError: name 'glob' is not defined

Upvotes: 11

Bryan Oakley
Bryan Oakley

Reputation: 386342

If it applies only to the class, it should be visible only to the class.

Upvotes: 5

Related Questions