Difference between 'function' and 'method'

castironpi at gmail.com castironpi at gmail.com
Tue Mar 4 13:16:59 EST 2008


On Mar 4, 5:27 am, Bruno Desthuilliers <bruno.
42.desthuilli... at wtf.websiteburo.oops.com> wrote:
> ?? a écrit :
>
> > Howdy everyone,
>
> >      This is a big problem puzzles me for a long time. The core question is:
> > How to dynamically create methods on a class or an instance?
>
> class Foo(object):
>     pass
>
> def bar(self, arg):
>     print "in bar : self == % - arg == %s" % (self, str(arg))
>
> def baaz(self, arg):
>     print "in baaz : self == % - arg == %s" % (self, str(arg))
>
> f = Foo()
>
> # adding bar as a method to class Foo
> Foo.bar = bar
>
> # f now can use bar:
> f.bar(42)
>
> # as well as new instances of Foo, of course
> g = Foo()
> g.bar()
>
> # adding baaz as a method to f, the old way:
> import new
> f.baaz = new.instancemethod(baaz, f, type(f))
>
> f.baaz()
>
> # adding baaz as a method to g, the other way:
> g.baaz = baaz.__get__(g, type(g))
>
> g.baaz()
>
> > Let me state it step by step.
> > 1.
> > def gunc(self):
> >     pass
> > class A(object):
> >     def func(self):
> >         pass
> > a = A()
> > a.func   # gives "bound method", type is "instancemethod"
> > A.func  # gives "unbound method", type is "instancemethod"
> > gunc    # gives "function", type if "function"
>
> > # ?? Does this line attach a method to instance?  ... I don't think so.
> > a.gunc = gunc
>
> It doesn't.
>
> > I found stardard library 'new' may help. Is that right?
>
> cf above. If you work with old-style classes, you'll need
> new.instancemethod.
>
> > 2.
> > a = A()  # instance of old class A
> > # Do attach a new method to class A...
> > b = A()  # instance of new class A
> > Does "a" can get the new method automatically?
>
> Yes. In Python, a class is itself an object, and is an attribute of it's
> instances (instance.__class__). Names are resolved at runtime, and
> attributes not found in the instance's __dict__ are looked up in the
> class (and then in the superclasses etc).
>
> > Does new method have the *same* concept level with old methods?
>
> The newly added method works exactly the same way as already existing
> ones. Not a single difference. The class statement is just syntactic
> sugar anyway. The following snippets are equivalent:
>
> # sugar-coated:
> class Boo(object):
>      faaz = 0
>
>      def far(self):
>          type(self).faaz += 1
>          print self
>
>      def frob(self):
>          print "yadda"
>
> # raw:
> def far(self):
>      type(self).faaz += 1
>      print self
>
> Boo = type('Boo', (object,), dict(faaz=0, far=far))
>
> def frob(self):
>     print "yadda"
>
> Boo.frob = frob
>
> > Especially, if there
> > are classes inherit from class A, how does name resolution work on this case?
>
> As usual.
>
> > 3.
> > How do I write a decroator for a method?
>
> Mostly the same way you'd write a decorator for a function
>
> > Eg:
> > class A(object):
> >     @my_dec
> >     def func(self):
> >         pass
> > Here, my_dec should return a method rathar than a function/lambda. Am I right?
>
> Nope. Functions defined within a class statement are plain ordinary
> functions. It's the lookup mechanism that "turns them into methods" when
> they are looked up as attribute of a class. In fact, Python "methods"
> are thin callable wrappers around a function, a class and (most of the
> time) an instance, wrappers which are created - usually at lookup time -
> by the __get__ method of the function type (you may want to read about
> the descriptor protocol on python.org - in the section about new style
> classes IIRC).
>
> Anyway, you can explore this by yourself:
>
>  >>> Boo.far
> <unbound method Boo.far>
>  >>> b.far
> <bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>  >>> Boo.__dict__['far']
> <function far at 0xb7c28aac>
>  >>> Boo.__dict__['far'] is far
> True
>  >>> f1 = b.far
>  >>> f2 = b.far
>  >>> f1 is f2
> False
>  >>> f1()
> <__main__.Boo object at 0xb787f96c>
>  >>> f2()
> <__main__.Boo object at 0xb787f96c>
>  >>> dir(f1)
> ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',
> '__get__', '__getattribute__', '__hash__', '__init__', '__new__',
> '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
> 'im_class', 'im_func', 'im_self']
>  >>> f1.im_class
> <class '__main__.Boo'>
>  >>> f1.im_func
> <function far at 0xb7c28aac>
>  >>> f1.im_func is far
> True
>  >>> f1.im_self
> <__main__.Boo object at 0xb787f96c>
>  >>> f1.im_self is b
> True
>  >>> bf = Boo.far
>  >>> bf.im_func
> <function far at 0xb7c28aac>
>  >>> bf.im_func is far
> True
>  >>> bf.im_class
> <class '__main__.Boo'>
>  >>> bf.im_self
>  >>> bf.im_self is None
> True
>  >>> far.__get__(b, Boo)
> <bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>  >>> far.__get__(b, Boo).im_func is far
> True
>  >>>
>
> 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.



More information about the Python-list mailing list