我不清楚用静态方法设计一个类的最佳方法是什么,静态方法应该是可重写的。我将试着用一个例子来解释。
我们有一个类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
的代码知道billy
是Goat
的实例,并错误地假设其类型是Goat
,而实际上它可能是Goat
的任何子类型。或者它错误地假设子类不会重写静态方法。
在我看来,这似乎是一个容易犯的错误;也许Goat
在引入这个bug时没有任何子类,所以没有注意到这个bug。
我们如何设计和记录一个类以避免此类错误?特别是,这个例子中的can_climb
应该是静态方法还是应该使用其他方法?
继承显然意味着对基类的了解。
@staticmethod
不知道它“附加”到的类(因此它们以前不是每天都叫它“unbound”;现在从技术上讲@staticmethod
根本不是一个方法;它是一个函数。但是
@classmethod
完全知道它附加到的类;从技术上讲,它不是函数,而是方法。那为什么
@staticmethod
呢?它是在派生类中继承的,但如前所述,不了解基类;我们可以“按原样”使用它,就好像在派生类中定义了它一样。非技术性地说,
@classmethod
是'bounded';@staticmethod
不是。如果有人问我,我会建议给
@staticfunction
取个名字。相关问题 更多 >
编程相关推荐