Counting number of objects

Mark Wooding mdw at distorted.org.uk
Mon Jan 26 03:37:37 CET 2009


Andreas Waldenburger <geekmail at usenot.de> writes:

> On Sun, 25 Jan 2009 09:23:35 -0800 (PST) Kottiyath
> <n.kottiyath at gmail.com> wrote:
>
>> class a(object):
>>     counter = 0
>>     def __new__(cls, *args, **kwargs):
>>         a.counter += 1
>>         return object.__new__(cls, *args, **kwargs)

Hmm.  Exceptions raised during object creation make this rather
precarious.  In your code, if object.__new__ raises an exception, the
counter will end up too high (the __del__ method won't get called in
this case).

One might try to rewrite it:

        def __new__(cls, *args, **kw):
          thing = object.__new__(cls, *args, **kw)
          a.counter += 1
          return thing

Now this won't work in subclasses if they also have a __new__ method:
again, if the subclass's __new__ raises an exception then __del__ won't
be called and the counter will be too high.

To make this technique work, I think you need to do the counter
increment in __init__ rather than __new__, and to set an attribute so
that __del__ knows whether to do the decrement.  (If a subclass's
__init__ raises an exception before yours gets called, you don't want to
do the decrement because that'll leave the counter too low.)

> This looks OK, although I'd suggest using "cls.counter += 1" instead
> of "a.counter += 1" in the __new__() method. Just seems clearer to me,
> esp. when you think about subclassing. 

I'm not sure about clarity, but that would be semantically different.
The code as written counts all instances of a and its subclasses.  Your
suggestion would count instances of subclasses independently.  I don't
know which behaviour the OP would prefer, but I don't think choosing
between them is a matter of clarity.

> Another way to go would be to use the weakref module and create a
> weakref-set (or list) as the counter. That way you would only need to
> add the objects in the __new__() method and not worry about removing
> them. I will admit that this is overengineering the problem a bit, but
> might be a good exercise.

This is a better approach, because it avoids the problems with
exceptions during object construction that I described above.

>> Another question - unrelated to the major topic:
>> How much time does it take to be proficient in Python?
> Don't concern yourself with that question at all, is my advice.

Indeed.  Besides, it varies an awful lot.

I can't tell you from my personal experience, because I tend to learn
programming languages by osmosis.  I sit and read language manuals and
newsgroups out of curiosity, because I find programming languages
intrinsically interesting.  One day, maybe a few years later, I start
writing programs in some language.  I'm usually up to half-decent
language-lawyer standards within a few days of this point -- but I've
had a /lot/ of practice at this game.  My approach is almost certainly
extremely atypical.

But one of the best things about Python is the library.  It's very big
and wide-ranging, but not overcomplex, and I'm still discovering cool
stuff, even though it's been there for years.  And the advice to keep
the Library Reference under your pillow is excellent.  Expect to be
flipping through it constantly.

>> - or am I just dumb?
> You're writing programs and you're communicating with like-minded
> people about your problems (in a socially appropriate way). Not what
> dumb people do, in my book.

Absolutely!  Besides, you're asking sensible questions about subtle
parts of the language -- I wouldn't say that __new__ was beginner
territory, for example.  So, no, you certainly don't seem dumb to me.

-- [mdw]



More information about the Python-list mailing list