Can __iter__ be used as a classmethod?

Giovanni Bajo noway at sorry.com
Tue Mar 4 13:29:24 EST 2003


"Alex Martelli" <aleax at aleax.it> ha scritto nel messaggio
news:b42ev802l51 at enews4.newsguy.com...

> Sure, let's -- no "classic classes" in the following (and, feel free
> to switch the discussion to it.comp.lang == with [Python] at the start
> of the subject == if discussing this in Italian will make it easier for
> you... otherwise, keeping it on c.l.py does seem preferable).

Is my english that bad? :)
It's ok to keep it in here, thanks anyway for the offer.

Your reply was pretty clear and exhaustive. I think the main problem is that
I was thinking of iter(B()) as a different way of calling B().__iter__
(usually 'inherited' from B.__iter__), and not type(B).__iter__. Everything
makes more sense now.

I still have a small doubt by classmethod(). Let's consider this:

class A:
    def f(cls):
        pass
    f = classmethod(f)

    def g(self):
        pass

a = A()

Now, in my current understanding, the differences between A.f and A.g are:

1) A.f() is a valid call (and the function will receive class A as
parameter), while A.g() will raise a runtime exception (unbound method).
A.g(a) is correct because it is equivalent to a.g().
2) a.f() is a valid call (and the function will receive class A, aka
type(a), as parameter); a.g() is a valid call as well, and the function will
receive a as parameter

Also, both are attributes of A and not of a. They can be used on a because
they are automatically looked up on type(a), but they belong to A.
Another source of confusion in my mind is that type(A.g) is called "instance
method", because it must be bound to an instance of the class, to become
'callable'. But it does not 'belong' to the instance, it is actually defined
in A.__dict__, not in A().__dict__.

> > mean that rebinding B().__iter__ has no effect since B.__iter__ is
always
> > looked up when iterating over instances of B(), while B().f() can be
> > freely rebound?
>
> It's not true that rebinding name '__iter__' on an instance has NO
> effect --

Yes, it should have been 'has no effect with respect to iterating over B
instances'.

> it does affect calls DIRECTLY to thatinstance.__iter__, AND
> iterations on INSTANCES of that instance (if, of course, that instance
> is usable and gets used as a type. AKA class).  But it has no effect
> on ITERATIONS on that instance, or calls to iter(...) with that
> instance as their argument.

So, if I rebind B().__iter__, Python will use the rebound function when
calling "for x in B().__iter__()" (assuming that 'B()' always refers to the
same instance of course) but it will not change "for x in B", which is
semantically the same of "for x in iter(B)", or "for x in
type(B).__iter__()" (maybe modulo obscure situations that I can ignore for
now).

> [snip]
> This
> may help explain why inheritance is not transitive AND why the
> operations and built-ins access special attributes on the TYPES
> of their arguments, not on their arguments themselves.

Yes, I understand very well why 'inheritance' cannot be transitive. By the
way, it seems that the word 'inheritance' has been abused in this context:
this is not the normal inheritance as in class A(B), but something different
(A() will lookup attributes from A if they have not been rebound, and A will
lookup attributes from A.__metaclass__ -- more generically, A will lookup
attributes in type(A)). Is there a more correct word for this?
'meta-inheritance'? :)

Thanks again for your time

Giovanni Bajo






More information about the Python-list mailing list