__class__ of what

Stefan Schwarzer sschwarzer at sschwarzer.net
Thu Aug 12 11:05:45 EDT 2010


Hello Jean-Michel,

On 2010-08-12 16:06, Jean-Michel Pichavant wrote:
> Eric J. Van der Velden wrote:
> Should be
> 
> class C:
>     n = 0
>     def __init__(self):
>        self.__class__.n+=1
>        C.n+=1 # equivalent to this line (I prefer this one, more 
> readable, less refactor-friendly)

I think both lines have slightly different semantics if you
consider instantiating an object of a derived class. (The
following formatting is from IPython, thus the differences
to the "usual" interpreter output.)

    Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)

    >>> class C(object):
    ...     n = 0
    ...     def __init__(self):
    ...             self.__class__.n += 1
    ...
    >>> class D(C):
    ...     pass
    ...
    >>> d = D()
    >>> D.n
        1
    >>> C.n
        0

Here, the augmented assignment looks up self.__class__.n
which it doesn't find and so gets it from class C. The
actual assignment assigns to D.n, however.

On the other hand:

    >>> class C(object):
    ...     n = 0
    ...     def __init__(self):
    ...             C.n += 1
    ...
    >>> class D(C):
    ...     pass
    ...
    >>> d = D()
    >>> D.n
        1
    >>> C.n
        1

Here, only C is changed. D doesn't get an own attribute n,
and after the instantiation of d, D.n looks up and gets n
from the base class C.

Curiously,

    >>> dir(D)
    ['__class__',
     '__delattr__',
     '__dict__',
     '__doc__',
     '__format__',
     '__getattribute__',
     '__hash__',
     '__init__',
     '__module__',
     '__new__',
     '__reduce__',
     '__reduce_ex__',
     '__repr__',
     '__setattr__',
     '__sizeof__',
     '__str__',
     '__subclasshook__',
     '__weakref__',
     'n']

seems to contain n (is it supposed to be listed here?), but

    >>> dict(D.__dict__)
        {'__doc__': None, '__module__': '__main__'}

indicates that D doesn't contain n. But C does:

    >>> dict(C.__dict__)
    {'__dict__': <attribute '__dict__' of 'C' objects>,
     '__doc__': None,
     '__init__': <function __init__ at 0xb70c2454>,
     '__module__': '__main__',
     '__weakref__': <attribute '__weakref__' of 'C' objects>,
     'n': 1}

I hope everything I wrote above is valid. If not, please
correct me. :-)

Anyway, depending on what you want, either of the two
variants might be ok. In any case I'd include a meaningful
comment on why you actually wrote what you wrote. :-)

Stefan



More information about the Python-list mailing list