I don't think either are pythonically correct for what you are trying to accomplish (assign a default value to a class attribute). Why would you not simply do this?
class Foo(object):
def __init__(self, a = 'init'):
self.a = a
self.spam = 2
And then:
>>> a_foo = Foo()
>>> a_foo.spam
2
>>> a_foo.spam = 3
>>> a_foo.spam
3
If you do it via a static class attribute (your second example), you can get very different behavior depending on how you assign/access it:
class Foo(object):
spam = 2
def __init__(self, a = 'init'):
self.a = a
and then:
>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> Foo.spam = 3
>>> a_foo1.spam
3
>>> a_foo2.spam
3
# But now they'll diverge
>>> a_foo1.spam = 5
>>> a_foo1.spam
5
>>> a_foo2.spam
3
>>> Foo.spam = 2
>>> a_foo1.spam
5
>>> a_foo2.spam
2
If you are trying to make it so that modifying any instance's copy of spam
modifies all instance's copies of spam
, you'd use a property combined with a static attribute
class Foo(object):
_spam = 2
def __init__(self, a = 'init'):
self.a = a
@property
def spam(self):
return Foo._spam
@spam.setter
def spam(self, value)
Foo._spam = value
>>> a_foo1 = Foo()
>>> a_foo2 = Foo()
>>> a_foo1.spam
2
>>> a_foo2.spam
2
>>> a_foo1.spam = 3
>>> a_foo2.spam
3
Although this kind of singleton-attribute behavior is somewhat dangerous and might be considered an anti-pattern by some, as most users of a class do not expect modifying one instance's attribute to modify all instances' attributes. You definitely need to have a very good reason for doing it this way.