使用@classmethod 的最大原因是在旨在被继承的备用构造函数中。这在多态性中非常有用。一个例子:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
@classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
注意Shape 是一个抽象类,它定义了一个类方法from_square,因为Shape 没有真正定义,它并不真正知道如何从Square 派生自己,所以它只是返回一个默认实例类的。
然后允许继承的类定义自己的此方法版本:
class Square(Shape):
def __init__(self, side=10):
self.side = side
@classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
@classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init__(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
@classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
该用法允许您以多态方式处理所有这些未实例化的类
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
您可能会说这一切都很好,但我为什么不能使用 @staticmethod 来完成同样的多态行为:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@staticmethod
def from_square(square):
return Circle(radius=square.length/2)
答案是你可以,但你没有得到继承的好处,因为Circle 必须在方法中显式调用。这意味着如果我从继承的类中调用它而不覆盖,我仍然会每次都得到Circle。
请注意,当我定义另一个实际上没有任何自定义 from_square 逻辑的形状类时会得到什么:
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
您可以在此处保留 @classmethod 未定义,它将使用来自 Shape.from_square 的逻辑,同时保留 cls 是谁并返回适当的形状。
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)