jfj <[EMAIL PROTECTED]> wrote: > I don't understand. > We can take a function and attach it to an object, and then call it > as an instance method as long as it has at least one argument: > > ############# > class A: > pass > > def foo(x): > print x > > A.foo = foo > a=A() > a.foo() > #############
Right. If you want to understand how this happens, look at the foo.__get__ special method, which makes foo (like every other function) a *descriptor*. One you've set foo as an attribute of class A, the access a.foo calls foo.__get__(a, A) which returns an object of class "instance method". > However this is not possible for another instance method: > > ############ > class A: > pass > > class B: > def foo(x,y) > print x,y > > b=B() > A.foo = b.foo What you're assigning here as an attribute of class A is not a descriptor: it does not have a special method __get__. > a=A() > > # error!!! > a.foo() Since A.foo does not have a method __get__, it's just returned when you access it (on instance a). It's already an instance method -- but it's bound to instance b of class B. > ############## > > Python complains that 'foo() takes exactly 2 arguments (1 given)'. > But by calling "b.foo(1)" we prove that it is indeed a function which takes > exactly one argument. Calling something does not prove it's a function. Python has a lot of callable objects, and functions are just one callable types. So, you're mistaken if you think that by calling (whatever) you prove said whatever is a function (of any kind). The error message you're seeing does come from a function -- the im_func attribute of b.foo, which is a function foo taking two arguments (created and set into class B by the "def foo(x, y):" above, even though you forgot the colon I'm sure you intended to type it). > Isn't that inconsistent? That Python has many callable types, not all of which are descriptors? I don't see any inconsistency there. Sure, a more generalized currying (argument-prebinding) capability would be more powerful, but not more consistent (there's a PEP about that, I believe). If what you want is to focus on the error message, you can completely separate it from the idea of having set b.foo as an attribute of class A. Just try calling b.foo() without arguments and you'll get exactly the same error message -- from the underlying function foo, which is also b.foo.im_func (the function's FIRST argument is bound to b.foo.im_self, which is b; whence the error being about function foo taking exactly two arguments and only one having been given). Alex -- http://mail.python.org/mailman/listinfo/python-list