Prev: Programming Puzzles? What's your favorite puzzle?
Next: Using elementtree to Create HTML Form / Set "selected"
From: Eric J. Van der Velden on 12 Aug 2010 09:43 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 12 Aug 2010 10:06 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 12 Aug 2010 10:07 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 12 Aug 2010 10:21 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 12 Aug 2010 11:05
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 |