0

Is there any difference in the following two pieces of code? If not, is one preferred over the other? Why would we be allowed to create class attributes dynamically?

Snippet 1

class Test(object):
    def setClassAttribute(self):
        Test.classAttribute = "Class Attribute"

Test().setClassAttribute()

Snippet 2

class Test(object):
    classAttribute = "Class Attribute"

Test()
Joel Christophel
  • 2,604
  • 4
  • 30
  • 49
  • 1
    I would use the second. It depends if you want to have control over the creation or not. If not I would avoid the lines of code and the extra function call. Also `setClassAttribute` should be a classmethod otherwise it's senseless. – wenzul Dec 02 '14 at 19:31
  • I agree with wenzul. They are equivalent, but woth #1, if you forget, you will have some interesting errors. – matsjoyce Dec 02 '14 at 19:33
  • It doesn't make sense to create a class instance in order to set an attribute of the class, so neither is preferred. Also, what is *your* opinion on the matter? – Ulrich Eckhardt Dec 02 '14 at 19:36
  • Other thing: I would from experience avoid class variables and methods. In most cases if you think the problem again and create another class, the class variables will be eliminated. – wenzul Dec 02 '14 at 19:38
  • 1
    https://archive.org/details/SeanKellyRecoveryfromAddiction – Ashwini Chaudhary Dec 02 '14 at 19:40
  • That's a good guess, it could also be a case of using a class where none is needed. That's a misconception that many programmers hold because they are taught how to OOP but not when to OOP. – Ulrich Eckhardt Dec 02 '14 at 20:06
  • wenzul, could you give an example of eliminating a class variable by creating a class? – Joel Christophel Dec 02 '14 at 20:11

3 Answers3

5

First, setting a class attribute on an instance method is a weird thing to do. And ignoring the self parameter and going right to Test is another weird thing to do, unless you specifically want all subclasses to share a single value.*

* If you did specifically want all subclasses to share a single value, I'd make it a @staticmethod with no params (and set it on Test). But in that case it isn't even really being used as a class attribute, and might work better as a module global, with a free function to set it.

So, even if you wanted to go with the first version, I'd write it like this:

class Test(object):
    @classmethod
    def setClassAttribute(cls):
        cls.classAttribute = "Class Attribute"

Test.setClassAttribute()

However, all that being said, I think the second is far more pythonic. Here are the considerations:

  • In general, getters and setters are strongly discouraged in Python.
  • The first one leaves a gap during which the class exists but has no attribute.
  • Simple is better than complex.

The one thing to keep in mind is that part of the reason getters and setters are unnecessary in Python is that you can always replace an attribute with a @property if you later need it to be computed, validated, etc. With a class attribute, that's not quite as perfect a solution—but it's usually good enough.


One last thing: class attributes (and class methods, except for alternate constructor) are often a sign of a non-pythonic design at a higher level. Not always, of course, but often enough that it's worth explaining out loud why you think you need a class attribute and making sure it makes sense. (And if you've ever programmed in a language whose idioms make extensive use of class attributes—especially if it's Java—go find someone who's never used Java and try to explain it to him.)

abarnert
  • 354,177
  • 51
  • 601
  • 671
1

It's more natural to do it like #2, but notice that they do different things. With #2, the class always has the attribute. With #1, it won't have the attribute until you call setClassAttribute.

You asked, "Why would we be allowed to create class attributes dynamically?" With Python, the question often is not "why would we be allowed to", but "why should we be prevented?" A class is an object like any other, it has attributes. Objects (generally) can get new attributes at any time. There's no reason to make a class be an exception to that rule.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
0

I think #2 feels more natural. #1's implementation means that the attribute doesn't get set until an actual instance of the class gets created, which to me seems counterintuitive to what a class attribute (vs. object attribute) should be.

rchang
  • 5,150
  • 1
  • 15
  • 25