__class__ of what

  • Thread starter Eric J. Van der Velden
  • Start date
E

Eric J. Van der Velden

Hello,

I have,

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


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

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

Thanks,

Eric J.
 
J

Jean-Michel Pichavant

Eric said:
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
 
E

Eric Brunel

"Eric J. Van der Velden said:
Hello,

I have,

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


I do

This is fine.

No it's not, at least in Python 2.x:Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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)

1

No you can't, again in Python 2.x: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Š
 
P

Peter Otten

Eric said:
I have,

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


I do

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

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

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:
.... def f(self): __class__
.... def g(self): pass
....
A.f.__closure__[0].cell_contents
A.g.__closure__ is None
True

Peter
 
S

Stefan Schwarzer

Hello Jean-Michel,

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)
... n = 0
... def __init__(self):
... self.__class__.n += 1
... ... pass
... 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.

... n = 0
... def __init__(self):
... C.n += 1
... ... pass
... 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,
['__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
{'__doc__': None, '__module__': '__main__'}

indicates that D doesn't contain n. But C does:
{'__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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,170
Messages
2,570,927
Members
47,469
Latest member
benny001

Latest Threads

Top