21

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

5
  • 6
    If only that one class needs it, putting it in the class keeps the module namespace clean. Note that you can access it via self.THRESHOLD, which will handle inheritance more neatly. Also, that quote from the docs doesn't say what you claim it does - immutability is not the same as being considered a constant. Commented Jul 28, 2015 at 14:22
  • 1
    I would agree with @jonrsharpe keep it within the class so it acts as a namespace and gives the constant context Commented Jul 28, 2015 at 14:23
  • "Mutable values" in this context is not "variable values". I means you shouldn't use lists and dicts (and many other mutable objects) unless you know what you're doing. Otherwise, always put the values inside the class. Commented Jul 28, 2015 at 14:24
  • Thanks for the feedback, and the self. tip. I will leave the question a while longer to see what others think too. Commented Jul 28, 2015 at 14:24
  • I agree with @JBernardo, be careful while using with self.THRESHOLD, it first look for instance var and then class var, you can manipulate the instance var self.THRESHOLD while keeping class var intact Commented Jul 28, 2015 at 14:39

2 Answers 2

12

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
Sign up to request clarification or add additional context in comments.

1 Comment

Doesn't it break Open-Closed Principle? Let's say the constant is list of files on which class operates, and you want to add a new file. Having such constant in a class makes you alter the class in this case, even though class' logic hasn't changed.
5

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

Comments

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.