Style question - defining immutable class data members

Maxim Khitrov mkhitrov at gmail.com
Sat Mar 14 15:01:14 EDT 2009


On Sat, Mar 14, 2009 at 2:07 PM, Gary Herron <gherron at islandtraining.com> wrote:
> Maxim Khitrov wrote:
>>
>> Very simple question on the preferred coding style. I frequently write
>> classes that have some data members initialized to immutable values.
>> For example:
>>
>> class Test(object):
>>    def __init__(self):
>>        self.some_value = 0
>>        self.another_value = None
>>
>> Similar effect can be achieved by defining some_value and
>> another_value for the entire class, like so:
>>
>> class Test(object):
>>    some_value = 0
>>    another_value = None
>>
>> The advantage of doing this is that the assignments are evaluated once
>> and thus the creation of that class is a bit faster. Access is still
>> performed through self.some_value and self.another_value. Is there a
>> reason to prefer the first style over the second?
>>
>> - Max
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Such things are often called class attributes, and the are fine.  If you
> look through Python's standard library,  you will find many examples of
> class attributes.
>
> However, you appear to have either a misuse or misconception of the word
> "immutable' here.   Whether the value you assign to a class attribute is
> mutable or immutable is irrelevant.   Also whether you plan on leaving the
> value constant or not is also not relevant.
> What does matter is this:  If every instance wants access to a single value
> (immutable or not), use a class attribute, otherwise use an instance
> attribute.
>
> Gary Herron

Perhaps a different example would help explain what I'm trying to do:

class Case1(object):
	def __init__(self):
		self.count = 0
		self.list  = []

	def inc(self):
		self.count += 1
		self.list.append(self.count)

	def val(self):
		return (self.count, self.list)

class Case2(object):
	count = 0
	list  = []

	def inc(self):
		self.count += 1
		self.list.append(self.count)

	def val(self):
		return (self.count, self.list)

for i in xrange(10):
	c1 = Case1()
	c2 = Case2()

	for j in xrange(i):
		c1.inc()
		c2.inc()

	v1, l1 = c1.val()
	v2, l2 = c2.val()

	print v1 == v2, l1 == l2

The only difference between Case1 and Case2 classes is where the count
and list attributes are defined. You will notice that for an immutable
type (count), this doesn't matter. On the last line, v1 == v2 is
always True. When the type is mutable (list), you must define it in
__init__. This isn't about class attributes or shared instance
attributes/constants. This is about a small optimization in defining
per-instance variables. This optimization only applies to immutable
types.

- Max



More information about the Python-list mailing list