我需要通过折叠一个方法来重构现有代码,该方法可以在彼此继承的各种类别之间复制粘贴到一个方法中。 所以我制作了以下代码:
class A(object):
def rec(self):
return 1
class B(A):
def rec(self):
return self.rec_gen(B)
def rec_gen(self, rec_class):
return super(rec_class, self).rec() + 1
class C(B):
def rec(self):
return self.rec_gen(C)
if __name__=='__main__':
b = B(); c = C()
print c.rec()
print b.rec()
输出:
3
2
让我感到困扰的是,在'rec'方法中,我需要告诉'rec_gen'它正在运行的类的上下文。 “rec_gen”有没有办法在运行时自行解决?
答案 0 :(得分:4)
此功能已添加到Python 3中 - 请参阅PEP 3135。简而言之:
class B(A):
def rec(self):
return super().rec() + 1
我认为您已经创建了错综复杂的rec()
/ rec_gen()
设置,因为您无法自动找到该类,但是如果您想要它,则无论如何都应该有效:
class A(object):
def rec(self):
return 1
class B(A):
def rec(self):
# __class__ is a cell that is only created if super() is in the method
super()
return self.rec_gen(__class__)
def rec_gen(self, rec_class):
return super(rec_class, self).rec() + 1
class C(B):
def rec(self):
# __class__ is a cell that is only created if super() is in the method
super()
return self.rec_gen(__class__)
Python 2中最简单的解决方案是使用私有成员来保存super
对象:
class B(A):
def __init__(self):
self.__super = super(B)
def rec(self):
return self.__super.rec() + 1
但是仍然需要在一个地方指定实际的类,如果你碰巧在类层次结构中有两个同名的类(例如来自不同的模块),这个方法就会破坏。
在PEP 3135存在之前,我们有几个人为Python 2自动解析配方 - 我的方法是self.super on ActiveState。基本上,它允许以下内容:
class B(A, autosuper):
def rec(self):
return self.super().rec() + 1
或者您正在调用具有相同名称的父方法(最常见的情况):
class B(A, autosuper):
def rec(self):
return self.super() + 1
对此方法的警告:
这很慢。我有一个版本坐在某处进行字节码操作,以提高速度。
这与PEP 3135不一致(虽然它是一个阶段的Python 3超级提案)。
这很复杂。
这是一个混合基类。
我不知道上述内容是否能满足您的要求。虽然你可以找到你所在的课程并将其传递给rec_gen()
,但是对于食谱进行了一些小改动 - 基本上将_getSuper()
中的类查找代码提取到自己的方法中。
答案 1 :(得分:1)
python 2.x的另一种解决方案是使用元类在所有子类中自动定义rec
方法:
class RecGen(type):
def __new__(cls, name, bases, dct):
new_cls = super(RecGen, cls).__new__(cls, name, bases, dct)
if bases != (object,):
def rec(self):
return super(new_cls, self).rec() + 1
new_cls.rec = rec
return new_cls
class A(object):
__metaclass__ = RecGen
def rec(self):
return 1
class B(A):
pass
class C(B):
pass
请注意,如果您只是尝试获得类似父类的数量,那么直接使用self.__class__.__mro__
会更容易:
class A(object):
def rec(self):
return len(self.__class__.__mro__)-1
class B(A):
pass
class C(B):
pass
答案 2 :(得分:0)
我不确定你想要实现什么,但是如果它只是为每个类返回一个不同的常量值的方法,那么使用类属性来存储该值。您的示例中并不清楚您需要去super()
附近的任何地方。
class A(object):
REC = 1
def rec(self):
return self.REC
class B(A):
REC = 2
class C(B):
REC = 3
if __name__=='__main__':
b = B(); c = C()
print c.rec()
print b.rec()