继承和基类方法调用Python

13

我希望在一个基类中调用同一类中的另一个方法,而不是在继承类中重写方法。

我希望下面的代码将打印出:

类B:6

类A:9

这是否可行?


# Base class definition
class ClassA(object):
    def __init__(self):
        print("Initializing A")

    # hoping that this function is called by this class's printFnX
    def fnX(self, x):
        return x**2

    def printFnX(self, x):
        print("ClassA:",self.fnX(x))

# Inherits from ClassA above
class ClassB(ClassA):
    def __init__(self):
        print("initizlizing B")

    def fnX(self, x):
        return 2*x

    def printFnX(self, x):
        print("ClassB:", self.fnX(x))
        ClassA.printFnX(self,x)

bx = ClassB()
bx.printFnX(3)

11
你是否愿意重新考虑一下你所选定的已接受答案?目前的选择对于大多数人和大多数使用场景来说都是非常糟糕的建议。 - Raymond Hettinger
2个回答

50
恭喜你,发现了Python双下划线名称修饰的激励用例 :-)
有关详细信息和实际示例,请参见:http://docs.python.org/tutorial/classes.html#private-variableshttp://docs.python.org/reference/expressions.html#atom-identifiers
以下是如何在您的示例中使用它:
# Base class definition
class ClassA(object):
    def __init__(self):
        print("Initializing A")

    # hoping that this function is called by this class's printFnX
    def fnX(self, x):
        return x**2
    __fnX = fnX

    def printFnX(self, x):
        print("ClassA:",self.__fnX(x))

# Inherits from ClassA above
class ClassB(ClassA):
    def __init__(self):
        print("initizlizing B")

    def fnX(self, x):
        return 2*x

    def printFnX(self, x):
        print("ClassB:", self.fnX(x))
        ClassA.printFnX(self,x)

bx = ClassB()
bx.printFnX(3)

这个使用案例被描述为在"The Art of Subclassing"中实现开闭原则的一种方式,该视频可以在http://www.youtube.com/watch?v=yrboy25WKGo&noredirect=1找到。


1
非常有见地。现在我知道双下划线命名方法的用途了! - Steven T. Snyder
可能不太明显的是,基类中的方法必须是公共的,或者您必须使用完全混淆的名称。 Python没有“protected”或“friend”限定符,因此在重构时,仅将def __doSomething(self):'从超类移动到基类中并不能使其从超类中访问。您要么必须将其公开为def doSomething(self):',要么使用混淆的名称。 - Bill Kidd

-5

通过将fnXprintFnX都设置为类方法,也可以实现相同的效果。

class ClassA(object):

    def __init__(self):
        print("Initializing A")

    # hoping that this function is called by this class's printFnX
    @classmethod
    def fnX(self, x):
        return x ** 2

    @classmethod
    def printFnX(self, x):
        print("ClassA:",self.fnX(x))

class ClassB(ClassA):
    def __init__(self):
        print("initizlizing B")

    def fnX(self, x):
        return 2*x

    def printFnX(self, x):
        print("ClassB:", self.fnX(x))
        ClassA.printFnX(x)


bx = ClassB()<br>
bx.printFnX(3)

这个答案比其他的更好...更优雅。谢谢。 - fodon
5
这根本不起作用。尝试从fnX内部访问实例变量,例如“self.y”。在classmethod中,“self”变量不再持有实例;相反,它变成了调用者实例的类,因此您完全无法访问实例变量。这种“模式”是一个灾难,不应该在你关心的代码中使用。 - Raymond Hettinger
1
我同意,它只是回答了他最初的问题,并且包含了你刚才描述的所有缺点。这里本质上没有模式。 - Anand Balachandran Pillai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接