我不清楚使用可以覆盖的静态方法设计类的最佳方法是什么。我将尝试用一个例子来解释。
我们有一个类Goat
,其方法为can_climb
。 (顺便说一下,这是Python 3,在Python 2中我会写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
的代码知道billy
是Goat
的一个实例,并且当它确实是任何子类型时,会错误地假设其类型为Goat
Goat
。或者它可能错误地假定子类不会覆盖静态方法。
在我看来,这似乎是一个容易犯的错误;也许Goat
在引入这个bug的时候没有任何子类,所以没有注意到这个bug。
我们如何设计和记录课程以避免这种错误?特别是,此示例中的can_climb
应该是静态方法还是应该使用其他方法?
答案 0 :(得分:9)
继承显然意味着对基类的了解。 @staticmethod
不知道它所附带的课程是什么? to(因此他们早些时候 - 不是现在 - 称为它&#39;未绑定;&#39;现在技术上@staticmethod
根本不是一种方法;它是一种功能。
但@classmethod
完全了解它附加的类;它在技术上不是一种功能,而是一种方法。
为什么然后@staticmethod
呢?它在派生类中继承,但如前所述,不知道基类;我们可以使用它这样的&#39;好像我们已在派生类中定义它。
非技术性@classmethod
s 'bounded';@staticmethod
不是。
如果有人问我,我会为@staticfunction
建议名称@staticmethod
。