Python constructors have particular semantics2c and ‘Foo.__init__’ doesn't qualify

Steve D'Aprano steve+python at pearwood.info
Thu Dec 15 18:28:55 EST 2016


On Fri, 16 Dec 2016 08:09 am, Terry Reedy wrote:

> The __init__ function *is* an 'instance method', but not a (bound)
> method object.  The distinction is important.  I admit that 'instance
> method' can be confusing if one does not understand the contextual
> meaning of the two words.  A 'method' is a function that is a class
> attribute. Being a method normally adds special behavior to the
> function.  An 'instance method', the default status of a method,  takes
> an *instance of the class* (or subclass) as first parameter.  A 'class
> method' (relatively rare) takes the *class* (or subclass) as first
> parameter.   A 'static method' (very rare) takes neither as first
> parameter and is really just a function.

I think that what Terry might be trying to get at is that there's actually
two distinct but related meanings for "instance method" in the context of
Python. (Other languages may be different.)

(Terry, forgive me if I'm misinterpreting what you are saying.)

The first is an object of type types.MethodType. Because functions and
methods are first-class values in Python, such instance methods could be
stuffed into lists, attached as attributes to unrelated objects, bound to
variables, etc. Instance methods are just a data type, and could come from
anywhere.

Proof of concept:

py> class X(object):
...     pass
...
py> x = X()
py> from types import MethodType
py> def method(self):
...     print("method bound to", self)
...
py> x.surprise = MethodType(method, "Hello world!")
py> x.surprise()
method bound to Hello world!


But the usual meaning of "instance method" is a function defined inside a
class body (with exceptions below):

class X(object):
    def method(self):
        ...


That is *conceptually* an instance method even if the implementation uses an
object of different type. In Python 2, retrieving "method" from either the
class or the instance returns something which matches both definitions of
object:

X.method returns an "unbound method", an object of type MethodType;
X().method returns a "bound method", also an object of type MethodType.


But in Python 3, it is recognised that there is little or no conceptual
difference between an unbound method and a function, and the implementation
is changed:

X.method returns an "unbound method", an object of type FunctionType;
X().method returns a "bound method", an object of type MethodType.


But whether the implementation is a special form of MethodType or just
FunctionType, the object is still conceptually an instance method.


The exceptions to the "function defined inside a class body" rule includes
two built-in types used as decorators:

classmethod
staticmethod

which are deemed to be "kinds of methods" but not *instance* methods. In
Python, we call them "class methods" and "static methods", but in other
languages they may not exist at all or have other names.

(In Java, the closest equivalent to "class method" is called a "static
method".)



Adding to the complexity, the __name__ of MethodType is just "method", and
the __name__ of FunctionType is just "function", so introspecting the
objects (looking at their repr() etc) may give slightly different results.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.



More information about the Python-list mailing list