Difference between 'function' and 'method'

castironpi at gmail.com castironpi at gmail.com
Wed Mar 5 03:30:26 CET 2008


On Mar 4, 8:11 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar> wrote:
> En Tue, 04 Mar 2008 16:45:40 -0200, <castiro... at gmail.com> escribió:
>
> >> > So, to answer your question: what you are decorating are functions,  
> >> not
> >> > methods.
>
> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
> >> is it makes it.
>
> >>>> from types import FunctionType, MethodType
> >>>> class A( FunctionType ): pass
> > ...
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > TypeError: type 'function' is not an acceptable base type
>
> Use delegation instead of inheritance. This class is almost  
> indistinguishable from a true function (when used as a method):
>
> py> class myfunction(object):
> ...   __slots__ = ('func',)
> ...   #
> ...   def __init__(self, func):
> ...     object.__setattr__(self, 'func', func)
> ...   #
> ...   def __get__(self, instance, owner):
> ...     print "__get__ called for",instance
> ...     return self.func.__get__(instance, owner)
> ...   #
> ...   def __getattr__(self, name):
> ...     return getattr(self.func, name)
> ...   #
> ...   def __setattr__(self, name, value):
> ...     object.__setattr__(self.func, name, value)
> ...
> py>
> py> class P(object):
> ...   def foo(self, x): print 'foo',x
> ...   #
> ...   @myfunction
> ...   def bar(self, x): print 'bar',x
> ...
> py> p = P()
> py> p.foo(1)
> foo 1
> py> p.bar(2)
> __get__ called for <__main__.P object at 0x00A3D650>
> bar 2
> py> P.foo(p, 1)
> foo 1
> py> P.bar(p, 2)
> __get__ called for None
> bar 2
> py> print "p.foo", p.foo, type(p.foo)
> p.foo <bound method P.foo of <__main__.P object at 0x00A3D650>> <type  
> 'instancem
> ethod'>
> py> print "p.bar", p.bar, type(p.bar)
> p.bar __get__ called for <__main__.P object at 0x00A3D650>
> <bound method P.bar of <__main__.P object at 0x00A3D650>> __get__ called  
> for <__
> main__.P object at 0x00A3D650>
> <type 'instancemethod'>
> py> print set(dir(p.foo))==set(dir(p.bar))
> __get__ called for <__main__.P object at 0x00A3D650>
> True
> py> print "P.foo", P.foo, type(P.foo)
> P.foo <unbound method P.foo> <type 'instancemethod'>
> py> print "P.bar", P.bar, type(P.bar)
> P.bar __get__ called for None
> <unbound method P.bar> __get__ called for None
> <type 'instancemethod'>
> py> print set(dir(P.foo))==set(dir(P.bar))
> __get__ called for None
> True
> py> P.__dict__['foo']
> <function foo at 0x00A3BCB0>
> py> P.__dict__['bar']
> <__main__.myfunction object at 0x00A3D690>
>
> Ok, let's try returning a different thing from __get__: bound method ->  
> partial with self already bound; unbound method -> the original function.
>
> py> from functools import partial
> py>
> py> class myfunction2(myfunction):
> ...   def __get__(self, instance, owner):
> ...     if instance is None:
> ...         return self.func
> ...     return partial(self.func, instance)
> ...
> py> @myfunction2
> ... def baz(self, x): print 'baz',x
> ...
> py> P.baz = baz
> py> print p.baz
> <functools.partial object at 0x00A3E5A0>
> py> print P.baz
> <function baz at 0x00AB1030>
> py> p.baz(3)
> baz 3
> py> P.baz(p,3)
> baz 3
>
> --
> Gabriel Genellina

I actually don't believe you-- bar is not bound to an instance when P
is initialized... er, instantiated.  However, the evidence indicates
my belief mechanism is faulty... and rather conclusively at that.
<moves to acquire new evidence>  If P calls __get__( you ), is p a
gotcha?



More information about the Python-list mailing list