Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
Peter, Spir - thanks for your time and effort! I am posting this query to few more Python mailers. Thank you, Sangeeth On Tue, Feb 25, 2014 at 5:22 AM, spir wrote: > On 02/24/2014 08:19 PM, Sangeeth Saravanaraj wrote: > >> Sorry, I should have described what I was trying! >> >> 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. >> >> You can safely assume that all the database operations are working fine! >> >> 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! >> >> What is the best way to do this?! >> >> Thank you, >> >> Sangeeth >> > > Your problem looks like a typical "crosscutting" (transversal) concern > addressed by AOP (Aspect Oriented Programming). Their usual example is in > fact logging. Look at the wikipedia page: > https://en.wikipedia.org/wiki/Aspect-oriented_programming > > Not that it would help you solve it _in python_, but this may serve at > least to better understand what kind of problem you are actually facing; > and why it is annoying in programming (with common languages); what may be > your options. > > [I have no better approach than yours, using magic metamethods, and a > decorator to wrap it all.] > > > d > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
On Mon, Feb 24, 2014 at 10:53 PM, Peter Otten <__pete...@web.de> wrote: > Sangeeth Saravanaraj wrote: > > > I am trying to capture an object initiation and deletion events using the > > __call__() and __del__() methods with the following approach. > > Note that there is no guarantee that __dell__ will ever be called. Usually > it is better to introduce a weakref with callback. > > > class A(object): > > def __init__(self, klass): > > print "A::__init__()" > > self._klass = klass > > > > def __call__(self): > > print "A::__call__()" > > return self._klass() > > > > def __del__(self): > > print "A::__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__() > > > > @A > > class B(Parent1, Parent2): > > def __init__(self): > > print "B::__init__()" > > super(B, self).__init__() > > > > def main(): > > b = B() > > > > if __name__ == "__main__": > > main() > > > > > > I decorate a class, say class B (whose object initiation and deletion I > > wanted to capture) with a decorator class A. Please note that the class B > > is derived from two classes - Parent1 & Parent2 and I want to use super() > > method to initialise the parent classes. > > > > When I executed the above code snippet, I ran into the following issue: > > > > > > A::__init__() > > A::__call__() > > B::__init__() > > Traceback (most recent call last): > > File "so.py", line 40, in > > main() > > File "so.py", line 36, in main > > b = B() > > File "so.py", line 10, in __call__ > > return self._klass() > > File "so.py", line 32, in __init__ > > super(B, self).__init__() > > TypeError: must be type, not A > > A::__del__() > > > > > > When I commented "super(B, self).__init__()" in the class B :: __init__() > > method, it returned an object of type B and I was able to see the prints > > in the __call__ and __del__ methods but the __init__() methods of the > base > > classes (Parent1 & Parent2) are not called! > > > > From the error message, what I could understand is - the object returned > > by A::__call__() is not of type B but of type A. But when I put a print > in > > the A::__call__() I could see it returns an object of type B and not A. > > > > 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()? > > You'd have to introduce a naming convention or rewrite your class to be > aware of the wrapping in some way: > > @A > class B(Parent1, Parent2): > def __init__(self): > print "B::__init__()" > super(B._klass, self).__init__() > > Not pretty. > > > Or, is there any other better way to capture the __call__ and __del__ > > events for an object of a certain class - if so, how?! > > Most certainly, but you have to give some details about what you are up to > first. > Sorry, I should have described what I was trying! 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. You can safely assume that all the database operations are working fine! 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! What is the best way to do this?! Thank you, Sangeeth > > > PS: > > http://stackoverflow.com/questions/21826854/typeerror-when-using-super- > method-with-class-decorator-for-a-derived-class > > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError
I am trying to capture an object initiation and deletion events using the __call__() and __del__() methods with the following approach. class A(object): def __init__(self, klass): print "A::__init__()" self._klass = klass def __call__(self): print "A::__call__()" return self._klass() def __del__(self): print "A::__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__() @A class B(Parent1, Parent2): def __init__(self): print "B::__init__()" super(B, self).__init__() def main(): b = B() if __name__ == "__main__": main() I decorate a class, say class B (whose object initiation and deletion I wanted to capture) with a decorator class A. Please note that the class B is derived from two classes - Parent1 & Parent2 and I want to use super() method to initialise the parent classes. When I executed the above code snippet, I ran into the following issue: A::__init__() A::__call__() B::__init__() Traceback (most recent call last): File "so.py", line 40, in main() File "so.py", line 36, in main b = B() File "so.py", line 10, in __call__ return self._klass() File "so.py", line 32, in __init__ super(B, self).__init__() TypeError: must be type, not A A::__del__() When I commented "super(B, self).__init__()" in the class B :: __init__() method, it returned an object of type B and I was able to see the prints in the __call__ and __del__ methods but the __init__() methods of the base classes (Parent1 & Parent2) are not called! >From the error message, what I could understand is - the object returned by A::__call__() is not of type B but of type A. But when I put a print in the A::__call__() I could see it returns an object of type B and not A. 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 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor