Skip to content
Advertisement

Terminology: A user-defined function object attribute?

According to Python 2.7.12 documentation, User-defined methods:

User-defined method objects may be created when getting an attribute of a class (perhaps via an instance of that class), if that attribute is a user-defined function object, an unbound user-defined method object, or a class method object. When the attribute is a user-defined method object, a new method object is only created if the class from which it is being retrieved is the same as, or a derived class of, the class stored in the original method object; otherwise, the original method object is used as it is.

I know that everything in Python is an object, so a “user-defined method” must be identical to a “user-defined method object“. However, I can’t understand why there is a “user-defined function object attribute”. Say, in the following code:

class Foo(object):
    def meth(self):
       pass

meth is a function defined inside a class body, and thus a method. So why can we have a “user-defined function object attribute”? Aren’t all attributes defined inside a class body?


Bouns question: Provide some examples illustrating how a user-defined method object is created by getting an attribute of a class. Isn’t objects defined in their class definition? (I know methods can be assigned to a class instance, but that’s monkey patching.)

I’m asking for help because this part of document is really really confusing to me, a programmer who only knows C, since Python is such a magical language that supports both functional programming and object-oriented programmer, which I haven’t mastered yet. I’ve done a lot of search, but still can’t figure that out.

Advertisement

Answer

When you do

class Foo(object):
    def meth(self):
       pass

you are defining a class Foo with a method meth. However, when this class definition is executed, no method object is created to represent the method. The def statement creates an ordinary function object.

If you then do

Foo.meth

or

Foo().meth

the attribute lookup finds the function object, but the function object is not used as the value of the attribute. Instead, using the descriptor protocol, Python calls the __get__ method of the function object to construct a method object, and that method object is used as the value of the attribute for that lookup. For Foo.meth, the method object is an unbound method object, which behaves like the function you defined, but with an extra type checking of self. For Foo().meth, the method object is a bound method object, which already knows what self is.


This is why Foo().meth() doesn’t complain about a missing self argument; you pass 0 arguments to the method object, which then prepends self to the (empty) argument list and passes the arguments on to the underlying function object. If Foo().meth evaluated to the meth function directly, you would have to pass it self explicitly.


In Python 3, Foo.meth doesn’t create an unbound method object; the function’s __get__ still gets called, but it returns the function directly, since Guido decided unbound method objects weren’t useful. Foo().meth still creates a bound method object, though.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement