—
Sent from Mailbox for iPad
On Mon, Feb 24, 2014 at 8:49 PM, David Lawrence <da...@bitcasa.com> wrote:
> 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 *release()* method on your objects and calling it
> explicitly before calling *del my_obj *(if you even call del, rather than
> just relying on GC).
> Alternatively, if it suits the scenario, use a context manager.
> All suggestions lifted from (a SO that informed me in the past):
> http://stackoverflow.com/questions/6104535/i-dont-understand-this-python-del-behaviour
> On Mon, Feb 24, 2014 at 6:24 PM, Alex Martelli <al...@google.com> wrote:
>> 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.
>>
>> No time to actually write the code but this seems a much sounder
>> architecture.
>>
>>
>> Alex
>>
>>
>>
>> On Mon, Feb 24, 2014 at 4:49 PM, Sangeeth Saravanaraj <
>> sangeeth.saravana...@gmail.com> wrote:
>>
>>> This question was initially asked in tu...@python.org; Now I am widening
>>> the audience to gain attention.
>>>
>>> I want to create a decorator which should do the following things:
>>> => 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.
>>> => When an object of the decorated class is deleted, the record with
>>> this deleted objects name (i.e. object.id) should be removed from the
>>> table.
>>>
>>> Now, for example - consider the following snippet:
>>>
>>> @saveme
>>> class A(object):
>>> def __init__(self, id):
>>> self.id = id
>>>
>>> @saveme
>>> class B(object):
>>> def __init__(self, id):
>>> self.id = id
>>>
>>> "saveme" should do what I have explained earlier.
>>>
>>> a1 = A("A1")
>>> a2 = A("A2")
>>> a3 = A("A3")
>>> b1 = B("B1")
>>> b2 = B("B2")
>>>
>>> At this point if I query and print all the records in a table, I should
>>> get the following output:
>>> ["A1", "A2", "A3", "B1", "B2"]
>>>
>>> del a1
>>> del a2
>>> del a3
>>> del b1
>>> del b2
>>>
>>> At this point, all entries in the table should be deleted; query should
>>> return an empty list!
>>>
>>> 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]!
>>>
>>> Now the following is what I have tried:
>>>
>>> class saveme(object):
>>> def __init__(self, klass):
>>> print "saveme::__init__()"
>>> self._klass = klass
>>>
>>> def __call__(self, *args, **kwargs):
>>> print "saveme::__call__()"
>>> obj = self._klass(*args, **kwargs)
>>> # creation of DB record will happen here!
>>> # i.e. something like add_to_db(kwargs.get("id"))
>>> return obj
>>>
>>> def __del__(self):
>>> # deletion of DB record will happen here!
>>> # i.e. something like remove_from_db(id)
>>> # TODO: how to retrieve the "id" here?!
>>> print "saveme::__del__()"
>>>
>>>
>>> class Parent1(object):
>>> def __init__(self):
>>> print "Parent1:: __init__()"
>>> super(Parent1, self).__init__()
>>>
>>>
>>> class Parent2(object):
>>> def __init__(self):
>>> print "Parent2:: __init__()"
>>> super(Parent2, self).__init__()
>>>
>>>
>>> @saveme
>>> class A(Parent1, Parent2):
>>> def __init__(self, id):
>>> print "A::__init__()"
>>> self.id = id
>>> #super(A, self).__init__()
>>>
>>>
>>> #@saveme
>>> #class B(object):
>>> # def __init__(self, id):
>>> # print "B::__init__()"
>>> # self.id = id
>>>
>>>
>>> def main():
>>> a1 = A(id="A1")
>>> # b1 = B(id="B1")
>>>
>>> if __name__ == "__main__":
>>> main()
>>>
>>>
>>> When executed the above, I ran in to the following:
>>>
>>> saveme::__init__()
>>> saveme::__call__()
>>> A::__init__()
>>> Traceback (most recent call last):
>>> File "1.py", line 54, in <module>
>>> main()
>>> File "1.py", line 50, in main
>>> a1 = A(id="A1")
>>> File "1.py", line 10, in __call__
>>> obj = self._klass(*args, **kwargs)
>>> File "1.py", line 39, in __init__
>>> super(A, self).__init__()
>>> TypeError: must be type, not saveme
>>> saveme::__del__()
>>>
>>>
>>> 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!
>>>
>>> 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.
>>>
>>> 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()?
>>>
>>> Or, is there any other better way to capture the __call__ and __del__
>>> events for an object of a certain class - if so, how?!
>>>
>>> Thank you,
>>>
>>> Sangeeth
>>>
>>>
>>> PS:
>>> http://stackoverflow.com/questions/21826854/typeerror-when-using-super-method-with-class-decorator-for-a-derived-class
>>>
>>>
>>> _______________________________________________
>>> Baypiggies mailing list
>>> baypigg...@python.org
>>> To change your subscription options or unsubscribe:
>>> https://mail.python.org/mailman/listinfo/baypiggies
>>>
>>
>>
>> _______________________________________________
>> Baypiggies mailing list
>> baypigg...@python.org
>> To change your subscription options or unsubscribe:
>> https://mail.python.org/mailman/listinfo/baypiggies
>>
--
https://mail.python.org/mailman/listinfo/python-list