Note that there are some explanatory texts on larger screens.

plurals
  1. POPython: How do I dynamically alter methods of dict and list objects?
    text
    copied!<p>Here is a mockup of what I want to do:</p> <pre><code>alist = [1,2,3,4,5] # create a vanilla python list object replacef (alist) # replace __setitem__, extend,... with custom functions alist[0]=2 # now the custom __setitem__ is called </code></pre> <p>This is for a DSL project where the syntax should be as close to normal python as possible, so subclassing list and making the user call something like alist = MyList(1,2,3,4,5) is not desirable. Also, because the DSL needs to coexist with other libraries, globally changing list and dict is not an option...</p> <p>I have tried creating instancemethods and setting them directly on the object like alist.append = myFunc, but Python says those properties are read only. Changing the <code>__class__</code> attribute seems to be not permitted as well.</p> <p>Is what I am trying to do even possible in Python?</p> <p><strong>Update</strong>: here are some findings on what is possible with a subclass of object:</p> <p>Given:</p> <pre><code>class y(object): def __init__(self,a,b,c): self.a = a self.b = b self.c = c def f(self): print self print self.a print self.b print self.c class x(object): def __init__(self,a,b,c): self.a = a self.b = b self.c = c def f(self): print "x.f()" &gt;&gt;&gt; objy = y(1,2,3) &gt;&gt;&gt; objx = x(4,5,6) &gt;&gt;&gt; objy.f() &lt;__main__.y object at 0x02612650&gt; 1 2 3 &gt;&gt;&gt; objx.f() x.f() </code></pre> <p>It is possible to change the class of objx on the fly like this:</p> <pre><code>&gt;&gt;&gt; objx.__class__ = y &gt;&gt;&gt; objx.f() &lt;__main__.y object at 0x02612D90&gt; 4 5 6 </code></pre> <p>Also, one can dynamically add/change object methods on the fly, much like in javascript:</p> <pre><code>&gt;&gt;&gt; def g(self,p): print self print p &gt;&gt;&gt; import new &gt;&gt;&gt; objy.g = new.instancemethod(g,objy,y) &gt;&gt;&gt; objy.g(42) &lt;__main__.y object at 0x02612650&gt; 42 </code></pre> <p>However, both approaches will fail with objects that are implemented in C like dict and list:</p> <pre><code>&gt;&gt;&gt; def mypop(self): print "mypop" list.mypop(self) &gt;&gt;&gt; alist.pop = new.instancemethod(mypop,alist,list) AttributeError: 'list' object attribute 'pop' is read-only &gt;&gt;&gt; x = [1,2,3,4,5] &gt;&gt;&gt; x.__class__ = mylist TypeError: __class__ assignment: only for heap types </code></pre> <p>The suggested approach to use something like alist = replacef(alist) would not work here, because replacef could be called from a <code>__setattribute__</code> call like this: </p> <pre><code>alist = [1,2,3,4,5] aDSLObject.items = alist # __setattribute__ calls replacef on alist alist[0] = .... </code></pre> <p>So while it indeed is possible to change object methods dynamically, it seems like it is not possible to alter the behaviour of objects implemented in C - or am I missing something?</p>
 

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