Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Consolidating Jason Pratt's and the community wiki answers, with a look at the results of different methods of binding:</p> <p>Especially note how adding the binding function as a class method <em>works</em>, but the referencing scope is incorrect.</p> <pre><code>#!/usr/bin/python -u import types import inspect ## dynamically adding methods to a unique instance of a class # get a list of a class's method type attributes def listattr(c): for m in [(n, v) for n, v in inspect.getmembers(c, inspect.ismethod) if isinstance(v,types.MethodType)]: print m[0], m[1] # externally bind a function as a method of an instance of a class def ADDMETHOD(c, method, name): c.__dict__[name] = types.MethodType(method, c) class C(): r = 10 # class attribute variable to test bound scope def __init__(self): pass #internally bind a function as a method of self's class -- note that this one has issues! def addmethod(self, method, name): self.__dict__[name] = types.MethodType( method, self.__class__ ) # predfined function to compare with def f0(self, x): print 'f0\tx = %d\tr = %d' % ( x, self.r) a = C() # created before modified instnace b = C() # modified instnace def f1(self, x): # bind internally print 'f1\tx = %d\tr = %d' % ( x, self.r ) def f2( self, x): # add to class instance's .__dict__ as method type print 'f2\tx = %d\tr = %d' % ( x, self.r ) def f3( self, x): # assign to class as method type print 'f3\tx = %d\tr = %d' % ( x, self.r ) def f4( self, x): # add to class instance's .__dict__ using a general function print 'f4\tx = %d\tr = %d' % ( x, self.r ) b.addmethod(f1, 'f1') b.__dict__['f2'] = types.MethodType( f2, b) b.f3 = types.MethodType( f3, b) ADDMETHOD(b, f4, 'f4') b.f0(0) # OUT: f0 x = 0 r = 10 b.f1(1) # OUT: f1 x = 1 r = 10 b.f2(2) # OUT: f2 x = 2 r = 10 b.f3(3) # OUT: f3 x = 3 r = 10 b.f4(4) # OUT: f4 x = 4 r = 10 k = 2 print 'changing b.r from {0} to {1}'.format(b.r, k) b.r = k print 'new b.r = {0}'.format(b.r) b.f0(0) # OUT: f0 x = 0 r = 2 b.f1(1) # OUT: f1 x = 1 r = 10 !!!!!!!!! b.f2(2) # OUT: f2 x = 2 r = 2 b.f3(3) # OUT: f3 x = 3 r = 2 b.f4(4) # OUT: f4 x = 4 r = 2 c = C() # created after modifying instance # let's have a look at each instance's method type attributes print '\nattributes of a:' listattr(a) # OUT: # attributes of a: # __init__ &lt;bound method C.__init__ of &lt;__main__.C instance at 0x000000000230FD88&gt;&gt; # addmethod &lt;bound method C.addmethod of &lt;__main__.C instance at 0x000000000230FD88&gt;&gt; # f0 &lt;bound method C.f0 of &lt;__main__.C instance at 0x000000000230FD88&gt;&gt; print '\nattributes of b:' listattr(b) # OUT: # attributes of b: # __init__ &lt;bound method C.__init__ of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; # addmethod &lt;bound method C.addmethod of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; # f0 &lt;bound method C.f0 of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; # f1 &lt;bound method ?.f1 of &lt;class __main__.C at 0x000000000237AB28&gt;&gt; # f2 &lt;bound method ?.f2 of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; # f3 &lt;bound method ?.f3 of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; # f4 &lt;bound method ?.f4 of &lt;__main__.C instance at 0x000000000230FE08&gt;&gt; print '\nattributes of c:' listattr(c) # OUT: # attributes of c: # __init__ &lt;bound method C.__init__ of &lt;__main__.C instance at 0x0000000002313108&gt;&gt; # addmethod &lt;bound method C.addmethod of &lt;__main__.C instance at 0x0000000002313108&gt;&gt; # f0 &lt;bound method C.f0 of &lt;__main__.C instance at 0x0000000002313108&gt;&gt; </code></pre> <p>Personally, I prefer the external ADDMETHOD function route, as it allows me to dynamically assign new method names within an iterator as well.</p> <pre><code>def y(self, x): pass d = C() for i in range(1,5): ADDMETHOD(d, y, 'f%d' % i) print '\nattributes of d:' listattr(d) # OUT: # attributes of d: # __init__ &lt;bound method C.__init__ of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # addmethod &lt;bound method C.addmethod of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # f0 &lt;bound method C.f0 of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # f1 &lt;bound method ?.y of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # f2 &lt;bound method ?.y of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # f3 &lt;bound method ?.y of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; # f4 &lt;bound method ?.y of &lt;__main__.C instance at 0x0000000002303508&gt;&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload