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()
7
  • 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. Commented Dec 2, 2014 at 19:31
  • I agree with wenzul. They are equivalent, but woth #1, if you forget, you will have some interesting errors. Commented Dec 2, 2014 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? Commented Dec 2, 2014 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. Commented Dec 2, 2014 at 19:38
  • 1
    archive.org/details/SeanKellyRecoveryfromAddiction Commented Dec 2, 2014 at 19:40

3 Answers 3

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.)

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.