dunder-docs (was Python is DOOMED! Again!)

Devin Jeanpierre jeanpierreda at gmail.com
Tue Feb 3 04:24:38 EST 2015


On Mon, Feb 2, 2015 at 6:07 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> Run this code:
>
> # === cut ===
>
> class K(object):
>     def f(self): pass
>
> def f(self): pass
>
> instance = K()
> things = [instance.f, f.__get__(instance, K)]
> from random import shuffle
> shuffle(things)
> print(things)
>
> # === cut ===
>
>
> You allege that one of these things is a method, and the other is not. I
> challenge you to find any behavioural or functional difference between the
> two. (Object IDs don't count.)
>
> If you can find any meaningful difference between the two, I will accept
> that methods have to be created as functions inside a class body.

In this particular case, there is none. What if the body of the
"method" was super().f() ?

Some methods can be defined outside of the body and still work exactly
the same, but others won't.

> Otherwise you are reduced to claiming that there is some sort of mystical,
> undetectable "essence" or "spirit" that makes one of those two objects a
> real method and the other one a fake method, even though they have the same
> type, the same behaviour, and there is no test that can tell you which is
> which.

It isn't mystical. There are differences in semantics of defining
methods inside or outside of a class that apply in certain situations
(e.g. super(), metaclasses). You have cherrypicked an example that
avoids them.

If one wants to say "A method can (...) by using super()", then
methods must be defined to only exist inside of class bodies.

Obviously, once you construct the correct runtime values, behavior
might be identical. The difference is in whether you can do different
things, not in behavior.

>> For an example we can all agree on, this is not an instance of
>> collections.Iterable, but the docs claim it is iterable:
>> https://docs.python.org/2/glossary.html#term-iterable
>>
>>     class MyIterable(object):
>>         def __getitem__(self, i): return i
>
> "Iterable" is a generic term, not a type. Despite the existence of the
> collections.Iterable ABC, "iterable" refers to any type which can be
> iterated over, using either of two different protocols.
>
> As I said above, if you wanted to argue that "method" was a general term for
> any callable attached to an instance or class, then you might have a point.
> But you're doing something much weirder: you are arguing that given two
> objects which are *identical* save for their object ID, one might be called
> a method, and the other not, due solely to where it was created. Not even
> where it was retrieved from, but where it was created.
>
> If you believe that "method or not" depends on where the function was
> defined, then this will really freak you out:
>
>
> py> class Q:
> ...     def f(self): pass  # f defined inside the class
> ...
> py> def f(self): pass  # f defined outside the class
> ...
> py> f, Q.f = Q.f, f  # Swap the "inside" f and the "outside" f.
> py> instance = Q()
> py> instance.f  # Uses "outside" f, so not a real method!
> <bound method Q.f of <__main__.Q object at 0xb7b8fcec>>
> py> MethodType(f, instance)  # Uses "inside" f, so is a real method!
> <bound method Q.f of <__main__.Q object at 0xb7b8fcec>>

You are really missing the point, if you think that surprises me.

-- Devin



More information about the Python-list mailing list