FAQ
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.

Search Discussions

  • Jean-Michel Pichavant at Aug 12, 2010 at 2:06 pm

    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
  • Eric Brunel at Aug 12, 2010 at 2:07 pm
    In article
    <72151646-65cb-47bb-bd55-e7eb67577c05 at z10g2000yqb.googlegroups.com>,
    "Eric J. Van der Velden" 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.
  • Peter Otten at Aug 12, 2010 at 2:21 pm

    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
  • Stefan Schwarzer at Aug 12, 2010 at 3:05 pm
    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

    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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedAug 12, '10 at 1:43p
activeAug 12, '10 at 3:05p
posts5
users5
websitepython.org

People

Translate

site design / logo © 2022 Grokbase