静态方法与继承设计

2024-04-20 07:25:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我不清楚用静态方法设计一个类的最佳方法是什么,静态方法应该是可重写的。我将试着用一个例子来解释。


我们有一个类Goat和一个方法can_climb。(顺便说一下,这是Python3,在Python2中我将编写class Goat(object):。)

class Goat:
    def __init__(self, *args):
        ...

    def can_climb(self, mountain):
        return mountain.steepness < 10

billy = Goat("Billy")
if billy.can_climb(mount_everest):
    print("wow Billy, impressive")

这按预期工作,但是方法can_climb不使用self。使其成为静态方法似乎更干净,pylint甚至为上述方法发出警告。所以让我们改变一下:

class Goat:
    def __init__(self, *args):
        ...

    @staticmethod
    def can_climb(mountain):
        return mountain.steepness < 10

billy = Goat("Billy")
if billy.can_climb(mount_everest):
    print("wow Billy, impressive")

接近尾端的billy.can_climb可以改为Goat.can_climb,在本例中不会有区别。有些人甚至认为通过类而不是实例来调用静态方法更加清晰和直接。

但是,当我们使用继承和多态性时,这会导致一个微妙的错误:

class Goat:
    def __init__(self, *args):
        ...

    @staticmethod
    def can_climb(mountain):
        return mountain.steepness < 10

class MountaineeringGoat(Goat):
    @staticmethod
    def can_climb(mountain):
        return True

billy = get_ourselves_a_goat_called_billy()
if Goat.can_climb(mount_everest):     # bug
    print("wow Billy, impressive")

调用Goat.can_climb的代码知道billyGoat的实例,并错误地假设其类型是Goat,而实际上它可能是Goat的任何子类型。或者它错误地假设子类不会重写静态方法。

在我看来,这似乎是一个容易犯的错误;也许Goat在引入这个bug时没有任何子类,所以没有注意到这个bug。


我们如何设计和记录一个类以避免此类错误?特别是,这个例子中的can_climb应该是静态方法还是应该使用其他方法?


Tags: 方法selfreturninitdef错误argscan
1条回答
网友
1楼 · 发布于 2024-04-20 07:25:50

继承显然意味着对基类的了解。@staticmethod不知道它“附加”到的类(因此它们以前不是每天都叫它“unbound”;现在从技术上讲@staticmethod根本不是一个方法;它是一个函数。

但是@classmethod完全知道它附加到的类;从技术上讲,它不是函数,而是方法。

那为什么@staticmethod呢?它是在派生类中继承的,但如前所述,不了解基类;我们可以“按原样”使用它,就好像在派生类中定义了它一样。

非技术性地说,@classmethod'bounded';@staticmethod不是。

如果有人问我,我会建议给@staticfunction取个名字。

相关问题 更多 >