Difference between 'function' and 'method'

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Wed Mar 5 03:11:56 CET 2008

En Tue, 04 Mar 2008 16:45:40 -0200, <castironpi 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> 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  
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>
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
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> 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

More information about the Python-list mailing list