Note that there are some explanatory texts on larger screens.

plurals
  1. PODynamically binding Python methods to an instance correctly binds the method names, but not the method
    primarykey
    data
    text
    <p>I'm writing a client for a group of RESTful services. The body of the REST calls have the same XML structure, given parameters. There are several dozen calls, and I will not be implementing all of them. As such, I want to make them easy to specify and easy to use. The REST methods are grouped by functionality in separate modules and will need to share the same urllib2 opener for authentication and cookies. Here's an example of how a method is declared:</p> <pre><code>@rest_method('POST', '/document') def createDocument(id, title, body): # possibly some validation on the arguments pass </code></pre> <p>All the developer has to care about is validation. The format of the XML (for POST and PUT) or the URL (for GET and DELETE) and the deserialization of the response is done in helper methods. The decorated methods are collected in a client object from which they will be executed and processed. For example:</p> <pre><code>c = RESTClient('http://foo.com', username, password) c.createDocument(1, 'title', 'body') </code></pre> <p>The code is done. The only issue is in attaching the decorated methods to the client class. Although all the decorated methods can be seen in the client instance, they all share the same definition, namely the last one to be bound. Here's a brief example which duplicates the behaviour I'm seeing:</p> <pre><code>import types class C(object): pass def one(a): return a def two(a, b): return a+b def bracketit(t): return '(%s)' % t c = C() for m in (one, two): new_method = lambda self, *args, **kwargs:\ bracketit(m(*args, **kwargs)) method = types.MethodType(new_method, c, C) setattr(C, m.__name__, method) print c.one print c.two print c.two(1, 2) print c.one(1) </code></pre> <p>When I run this, I get the following output:</p> <pre><code>&lt;bound method C.&lt;lambda&gt; of &lt;__main__.C object at 0x1003b0d90&gt;&gt; &lt;bound method C.&lt;lambda&gt; of &lt;__main__.C object at 0x1003b0d90&gt;&gt; (3) Traceback (most recent call last): File "/tmp/test.py", line 19, in &lt;module&gt; print c.one(1) File "/tmp/test.py", line 12, in &lt;lambda&gt; bracketit(m(*args, **kwargs)) TypeError: two() takes exactly 2 arguments (1 given) </code></pre> <p>I'm not sure why the two methods are bound in the same way. I haven't been able to find much documentation on how instancemethod binds methods to instances. What is going on underneath the hood, and how would I fix the above code so that the second call prints '(1)'?</p>
    singulars
    1. This table or related slice is empty.
    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.
 

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