From: Eric J. Van der Velden on
Hello,

I have,

class C:
n=0
def __init__(s):
__class__.n+=1


I do
>>> C()

This is fine. But of what thing I am taking the __class__ of?
I can also do

@staticmethod
def p():
print(__class__.n)

>>> C.p()
1

Thanks,

Eric J.



From: Jean-Michel Pichavant on
Eric J. Van der Velden wrote:
> Hello,
>
> I have,
>
> class C:
> n=0
> def __init__(s):
> __class__.n+=1
>
>

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)

@classmethod
def p(cls):
print(cls.n)

JM


From: Eric Brunel on
In article
<72151646-65cb-47bb-bd55-e7eb67577c05(a)z10g2000yqb.googlegroups.com>,
"Eric J. Van der Velden" <ericjvandervelden(a)gmail.com> wrote:

> Hello,
>
> I have,
>
> class C:
> n=0
> def __init__(s):
> __class__.n+=1
>
>
> I do
> >>> C()
>
> This is fine.

No it's not, at least in Python 2.x:
>>> C()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NameError: global name '__class__' is not defined

> But of what thing I am taking the __class__ of?

Nothing, precisely. You should write s.__class__ (and replace s by self
while you're at it).

> I can also do
>
> @staticmethod
> def p():
> print(__class__.n)
>
> >>> C.p()
> 1

No you can't, again in Python 2.x:
>>> C.p()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in p
NameError: global name '__class__' is not defined

Unless I'm missing something or something fundamental changed in Python
3, your examples do not work�

> Thanks,
>
> Eric J.
From: Peter Otten on
Eric J. Van der Velden wrote:

> I have,
>
> class C:
> n=0
> def __init__(s):
> __class__.n+=1
>
>
> I do
>>>> C()
>
> This is fine. But of what thing I am taking the __class__ of?
> I can also do
>
> @staticmethod
> def p():
> print(__class__.n)
>
>>>> C.p()
> 1

I had no idea that this existed. __class__ was probably added to make
super() calls without an explicit class argument possible in Python 3. It is
made available as a closure:

>>> class A:
.... def f(self): __class__
.... def g(self): pass
....
>>> A.f.__closure__[0].cell_contents
<class '__main__.A'>
>>> A.g.__closure__ is None
True

Peter
From: Stefan Schwarzer on
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