<div dir="ltr"><div><div>The best way to avoid relying on __del__ in this particular case may be to hold, rather than a plain list of the IDs, a list of weak references to instances.  When the "list of IDs" is asked for, it goes through a property that cleans up those weak refs that correspond to now-disappeared instances, before returning the requested list of IDs.  Now __del__ can usefully be removed (as its existence may interfere with GC of cyclical garbage), yet the list of IDs is guaranteed to return the list of still-existing instances' IDs, no matter what constructs or idioms have been used to create and remove instances.<br>

<br></div>This avoid relying on creators/destroyers of instances properly calling release and/or using the appropriate context manager; such reliance is sometimes inevitable, but for this particular spec it does not appear to be, thus, it might best be avoided.<br>

<br><br></div>Alex<br><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Feb 24, 2014 at 7:46 PM, David Lawrence <span dir="ltr"><<a href="mailto:david@bitcasa.com" target="_blank">david@bitcasa.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">If as according to the docs, there is no guarantee of __del__ being called, anything that relies on that seems unsafe (depending on how robust one needs the solutions to be).  Solutions I've seen elsewhere suggest creating something like a <i>release()</i> method on your objects and calling it explicitly before calling <i>del my_obj </i>(if you even call del, rather than just relying on GC).<div>

<br></div><div>Alternatively, if it suits the scenario, use a context manager.</div><div><br></div><div>All suggestions lifted from (a SO that informed me in the past): <a href="http://stackoverflow.com/questions/6104535/i-dont-understand-this-python-del-behaviour" target="_blank">http://stackoverflow.com/questions/6104535/i-dont-understand-this-python-del-behaviour</a></div>

</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Feb 24, 2014 at 6:24 PM, Alex Martelli <span dir="ltr"><<a href="mailto:aleax@google.com" target="_blank">aleax@google.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Off the cuff, I'd make saveme into a function, not a class; the saveme function would alter the class passed in as its only argument (saving __init__ and/or __del__ methods it may have and replacing them with other -- nested -- functions that call them and do the rest of the job) and return the same class object it received.<div>


<br></div><div>No time to actually write the code but this seems a much sounder architecture.</div><div><br></div><div><br></div><div>Alex</div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">

<div><div>
On Mon, Feb 24, 2014 at 4:49 PM, Sangeeth Saravanaraj <span dir="ltr"><<a href="mailto:sangeeth.saravanaraj@gmail.com" target="_blank">sangeeth.saravanaraj@gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div><div>
<div dir="ltr"><div class="gmail_default" style="font-family:'courier new',monospace"><div class="gmail_default">This question was initially asked in <a href="mailto:tutor@python.org" target="_blank">tutor@python.org</a>; Now I am widening the audience to gain attention.</div>



<div class="gmail_default"><br></div><div class="gmail_default">I want to create a decorator which should do the following things:</div><div class="gmail_default"> => When an object of the decorated class is created, the objects name (say the value of the incoming "id" argument) should be stored as a record in a table in a database. </div>



<div class="gmail_default"> => When an object of the decorated class is deleted, the record with this deleted objects name (i.e. <a href="http://object.id" target="_blank">object.id</a>) should be removed from the table. </div>


<div class="gmail_default">
<br></div><div class="gmail_default">Now, for example - consider the following snippet:</div><div class="gmail_default"><br></div><div class="gmail_default">@saveme</div><div class="gmail_default">class A(object):</div><div class="gmail_default">



    def __init__(self, id):</div><div class="gmail_default">        <a href="http://self.id" target="_blank">self.id</a> = id</div><div class="gmail_default"><br></div><div class="gmail_default">@saveme</div><div class="gmail_default">


class B(object):</div>
<div class="gmail_default">    def __init__(self, id):</div><div class="gmail_default">        <a href="http://self.id" target="_blank">self.id</a> = id</div><div class="gmail_default"><br></div><div class="gmail_default">


"saveme" should do what I have explained earlier.</div>
<div class="gmail_default"><br></div><div class="gmail_default">a1 = A("A1")</div><div class="gmail_default">a2 = A("A2")</div><div class="gmail_default">a3 = A("A3")</div><div class="gmail_default">



b1 = B("B1")</div><div class="gmail_default">b2 = B("B2")</div><div class="gmail_default"><br></div><div class="gmail_default">At this point if I query and print all the records in a table, I should get the following output: </div>



<div class="gmail_default">["A1", "A2", "A3", "B1", "B2"]</div><div class="gmail_default"><br></div><div class="gmail_default">del a1</div><div class="gmail_default">del a2</div>



<div class="gmail_default">del a3</div><div class="gmail_default">del b1</div><div class="gmail_default">del b2</div><div class="gmail_default"><br></div><div class="gmail_default">At this point, all entries in the table should be deleted; query should return an empty list!</div>



<div class="gmail_default"><br></div><div class="gmail_default">And, I want to highlight that the classes that are being decorated with "saveme" can de derived classes too [which initialises its base classes using super() method]!</div>



<div class="gmail_default"><br></div><div class="gmail_default">Now the following is what I have tried:</div><div class="gmail_default"><br></div><div class="gmail_default">class saveme(object):</div><div class="gmail_default">



    def __init__(self, klass):</div><div class="gmail_default">        print "saveme::__init__()"</div><div class="gmail_default">        self._klass = klass</div><div class="gmail_default"><br></div><div class="gmail_default">



    def __call__(self, *args, **kwargs):</div><div class="gmail_default">        print "saveme::__call__()"</div><div class="gmail_default">        obj = self._klass(*args, **kwargs)</div><div class="gmail_default">



        # creation of DB record will happen here!</div><div class="gmail_default">        # i.e. something like add_to_db(kwargs.get("id"))</div><div class="gmail_default">        return obj</div><div class="gmail_default">



<br></div><div class="gmail_default">    def __del__(self):</div><div class="gmail_default">        # deletion of DB record will happen here!</div><div class="gmail_default">        # i.e. something like remove_from_db(id)</div>



<div class="gmail_default">        # TODO: how to retrieve the "id" here?!</div><div class="gmail_default">        print "saveme::__del__()"</div><div class="gmail_default"><br></div><div class="gmail_default">



<br></div><div class="gmail_default">class Parent1(object):</div><div class="gmail_default">    def __init__(self):</div><div class="gmail_default">        print "Parent1:: __init__()"</div><div class="gmail_default">



        super(Parent1, self).__init__()</div><div class="gmail_default"><br></div><div class="gmail_default"><br></div><div class="gmail_default">class Parent2(object):</div><div class="gmail_default">    def __init__(self):</div>



<div class="gmail_default">        print "Parent2:: __init__()"</div><div class="gmail_default">        super(Parent2, self).__init__()</div><div class="gmail_default"><br></div><div class="gmail_default"><br></div>



<div class="gmail_default">@saveme</div><div class="gmail_default">class A(Parent1, Parent2):</div><div class="gmail_default">    def __init__(self, id):</div><div class="gmail_default">        print "A::__init__()"</div>



<div class="gmail_default">        <a href="http://self.id" target="_blank">self.id</a> = id</div><div class="gmail_default">        #super(A, self).__init__()</div><div class="gmail_default"><br></div><div class="gmail_default">


<br></div>
<div class="gmail_default">#@saveme</div><div class="gmail_default">#class B(object):</div><div class="gmail_default">#    def __init__(self, id):</div><div class="gmail_default">#        print "B::__init__()"</div>



<div class="gmail_default">#        <a href="http://self.id" target="_blank">self.id</a> = id</div><div class="gmail_default"><br></div><div class="gmail_default"><br></div><div class="gmail_default">def main():</div><div class="gmail_default">



    a1 = A(id="A1")</div><div class="gmail_default">#    b1 = B(id="B1")</div><div class="gmail_default"><br></div><div class="gmail_default">if __name__ == "__main__":</div><div class="gmail_default">



    main()</div><div class="gmail_default"><br></div><div class="gmail_default"><br></div><div class="gmail_default">When executed the above, I ran in to the following:</div><div class="gmail_default"><br></div><div class="gmail_default">



saveme::__init__()</div><div class="gmail_default">saveme::__call__()</div><div class="gmail_default">A::__init__()</div><div class="gmail_default">Traceback (most recent call last):</div><div class="gmail_default">  File "1.py", line 54, in <module></div>



<div class="gmail_default">    main()</div><div class="gmail_default">  File "1.py", line 50, in main</div><div class="gmail_default">    a1 = A(id="A1")</div><div class="gmail_default">  File "1.py", line 10, in __call__</div>



<div class="gmail_default">    obj = self._klass(*args, **kwargs)</div><div class="gmail_default">  File "1.py", line 39, in __init__</div><div class="gmail_default">    super(A, self).__init__()</div><div class="gmail_default">



TypeError: must be type, not saveme</div><div class="gmail_default">saveme::__del__()</div><div class="gmail_default"><br></div><div class="gmail_default"><div class="gmail_default" style="font-size:13px"><br></div><div class="gmail_default" style="font-size:13px">



When I commented "super(A, self).__init__()" in the class A :: __init__() method, it returned an object of type A and I was able to see the prints in the __call__ and __del__ methods but the __init__() methods of the base classes (Parent1 & Parent2) were not called! </div>



<div class="gmail_default" style="font-size:13px"><br></div><div class="gmail_default" style="font-size:13px">From the error message, what I could understand is - the object returned by saveme::__call__() is not of type A but of type saveme. But when I put a print in the saveme::__call__() I could see it returns an object of type A and not saveme.</div>



<div class="gmail_default" style="font-size:13px"><br></div><div class="gmail_default" style="font-size:13px">Now the question is - with this approach to capture the initiation and deletion events of an object, how do I initialise the base classes using super()? </div>



<div class="gmail_default" style="font-size:13px"><br></div><div class="gmail_default" style="font-size:13px">Or, is there any other better way to capture the __call__ and __del__  events for an object of a certain class - if so, how?!</div>



<div><br></div></div><div class="gmail_default">Thank you,</div><div class="gmail_default"><br></div><div class="gmail_default">Sangeeth</div><div class="gmail_default"><br></div><div class="gmail_default"><br></div><div class="gmail_default">



PS: <a href="http://stackoverflow.com/questions/21826854/typeerror-when-using-super-method-with-class-decorator-for-a-derived-class" target="_blank">http://stackoverflow.com/questions/21826854/typeerror-when-using-super-method-with-class-decorator-for-a-derived-class</a></div>



<div class="gmail_default"><br></div></div></div>
<br></div></div>_______________________________________________<br>
Baypiggies mailing list<br>
<a href="mailto:Baypiggies@python.org" target="_blank">Baypiggies@python.org</a><br>
To change your subscription options or unsubscribe:<br>
<a href="https://mail.python.org/mailman/listinfo/baypiggies" target="_blank">https://mail.python.org/mailman/listinfo/baypiggies</a><br></blockquote></div><br></div>
<br>_______________________________________________<br>
Baypiggies mailing list<br>
<a href="mailto:Baypiggies@python.org" target="_blank">Baypiggies@python.org</a><br>
To change your subscription options or unsubscribe:<br>
<a href="https://mail.python.org/mailman/listinfo/baypiggies" target="_blank">https://mail.python.org/mailman/listinfo/baypiggies</a><br></blockquote></div><br></div>
</div></div></blockquote></div><br></div>