[Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError

Peter Otten __peter__ at web.de
Mon Feb 24 18:23:26 CET 2014


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 <module>
>     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.

> PS:
> http://stackoverflow.com/questions/21826854/typeerror-when-using-super-
method-with-class-decorator-for-a-derived-class




More information about the Tutor mailing list