Question about accessing class-attributes.
Alex Martelli
aleax at aleax.it
Thu Apr 24 09:24:52 EDT 2003
Duncan Booth wrote:
> Nikolai Kirsebom <nikolai.kirsebom.NOJUNK at siemens.no> wrote in
> news:0kifav8dfcbu0t8j4qrrkq6ag7gcg1s062 at 4ax.com:
>
>> class A(object):
>> InstCount = 0
>> def __init__(self):
>> self.__class__.__dict__['InstCount'] += 1
>>
>> class B(A):
>> InstCount = 0
>>
>> class C(A):
>> InstCount = 0
>>
>> Is the syntax used for incrementing the class-attribute for every
>> instanciation 'the way' it should be done ?
>
> It would be more normal just to write:
>
> self.__class__.InstCount += 1
Yes, but do note that this may produce strange anomalies if some
subclass erroneously forgets to rebind InstCount in its body...:
>>> class A(object):
... InstCount = 0
... def __init__(self):
... self.__class__.InstCount += 1
...
>>> class B(A): pass
...
>>> a1=A()
>>> a2=A()
>>> b1=B()
>>> b2=B()
>>> B.InstCount
4
>>> A.InstCount
2
>>>
VERY unlikely to be what one wants, AND a rather subtle bug too.
The OP's direct access to __class__.__dict__ would ensure an
exception got raised upon instantiation of such an errant subclass.
> Alternatively you could create a class method to do the increment, but
> that is probably needlessly complex here.
Personally, I'd define a custom metaclass for this purpose. Maybe
I'm getting TOO familiar with those, but, it doesn't sound all that
complex at all to me...:
>>> class metaIC(type):
... def __new__(cls, name, bases, dict):
... dict['InstCount'] = 0
... return type.__new__(cls, name, bases, dict)
... def __call__(cls, *args, **kwds):
... cls.InstCount += 1
... return type.__call__(cls, *args, **kwds)
...
>>> class A(object):
... __metaclass__ = metaIC
...
>>> class B(A): pass
...
>>> a1=A(); a2=A(); a3=A()
>>> b1=B()
>>> A.InstCount
3
>>> B.InstCount
1
>>>
...isn't this smoother and handier? Or does it just look that way
to me, due to overexposure to custom metaclasses?-)
When I think of behavior to be associated with a CLASS rather than
its INSTANCES, such as this case, more and more my thoughts turn to
a custom metaclass to encapsulate that behavior. And why not? it
does seem to be the normal way of OO -- just as I'd think of the
class in order to define behavior for its instances...
Alex
More information about the Python-list
mailing list