S
Sangeeth Saravanaraj
This question was initially asked in (e-mail address removed); 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!
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/...thod-with-class-decorator-for-a-derived-class
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!
saveme::__call__() is not of type A but of type saveme. But when I put aFrom the error message, what I could understand is - the object returned by
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/...thod-with-class-decorator-for-a-derived-class