TypeError when using super method with class decorator for a derived class
首先,为冗长的解释道歉。
版本1-代码:类的类修饰器1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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__()" @A class B(object): def __init__(self): print"B::__init__()" def main(): b = B() if __name__ =="__main__": main() |
版本1-输出:
1 2 3 4 | A::__init__() A::__call__() B::__init__() A::__del__() |
号版本2-代码:显式初始化基类的派生类的类修饰器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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__() Parent1.__init__(self) Parent2.__init__(self) def main(): b = B() if __name__ =="__main__": main() |
版本2-输出:
1 2 3 4 5 6 7 | A::__init__() A::__call__() B::__init__() Parent1:: __init__() Parent2:: __init__() Parent2:: __init__() A::__del__() |
。版本3-代码:带有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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() |
版本3-输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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__() |
。问题:
版本1仅供参考。它解释了我要做的事情,即捕获
在第2版中,我也尝试过同样的方法来处理
但在版本3中,我也尝试过使用
主要问题是
1 | super(B, self) |
1 2 3 4 5 | class _B(Parent1, Parent2): def __init__(self): print"B::__init__()" super(_B, self).__init__() B = A(_B) |
号
或者使用一个不替换整个
另外,如果您想跟踪
这里有一个修饰符,它应该做您想要做的事情,而不存在将类包装成非类的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | def track_creation_and_deletion(klass): original_init = klass.__init__ try: original_del = klass.__del__ except AttributeError: def original_del(self): pass def new_init(self, *args, **kwargs): print '{}.{}.__init__'.format(klass.__module__, klass.__name__) return original_init(self, *args, **kwargs) def new_del(self): print '{}.{}.__del__'.format(klass.__module__, klass.__name__) return original_del(self) # functools.wraps doesn't play nicely with built-in methods, # so we handle it ourselves new_init.__name__ = '__init__' new_init.__doc__ = original_init.__doc__ new_init.__module__ = klass.__module__ new_init.__dict__.update(getattr(original_init, '__dict__', {})) new_del.__name__ = '__del__' new_del.__doc__ = original_del.__doc__ new_del.__module__ = klass.__module__ new_del.__dict__.update(getattr(original_del, '__dict__', {})) klass.__init__ = new_init klass.__del__ = new_del return klass |
其中大约一半是错误处理和复制一些元数据,以使新方法看起来像是由调用者定义的。关键部分是我们定义了新的
这种方法的一个局限性是,很难在我们的
我花了一些时间来理解为什么分别使用
- http://eli.thegreenplace.net/2009/06/12/saferry-using-destructors-in-python/
- 我不理解这种Python的行为
- 同样的主题也在python list mailer中讨论过-在这里查看线程-https://mail.python.org/pipermail/python-list/2014-february/667592.html
使用
其中一个建议是创建一个上下文管理器,它可以创建和删除特定类的对象。
我有下面的例子,哪种类型的模拟。请仔细看一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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__() def Controller(_cls): class Wrapper(_cls): def create(self, name): ret = _cls.create(self, name) print"Added to Database! ::", name # Database add here! return ret def remove(self, name): ret = _cls.remove(self, name) print"Deleted from Database! ::", name # Database delete here! return ret return Wrapper @Controller class Manager(object): def __init__(self): #print"Manager::__init__()" self._repo = [] def create(self, name): a = A(name) print"Object created ::", name self._repo.append(a) def remove(self, name): for i, item in enumerate(self._repo): if item._name == name: del self._repo[i] print"Object removed ::", name def display(self): for item in self._repo: print item class A(Parent1, Parent2): def __init__(self, name): #print"A::__init__()" self._name = name super(A, self).__init__() def __repr__(self): return self._name def main(): m1 = Manager() m1.create("apples") m1.create("oranges") m1.create("grapes") #m1.display() m1.remove("apples") #m1.display() if __name__ =="__main__": main() |
。
执行时,会产生以下结果:
1 2 3 4 5 6 7 8 | Object created :: apples Added to Database! :: apples Object created :: oranges Added to Database! :: oranges Object created :: grapes Added to Database! :: grapes Object removed :: apples Deleted from Database! :: apples |
这是我能想到的最安全的解决方法。欢迎提出建议!