Python类方法的例子是什么?
我看过Python中的类方法有什么用?这篇文章,但里面的例子太复杂了。我想找一个简单明了、基础的例子,来说明在Python中类方法的具体用法。
你能举一个小而具体的例子,说明在什么情况下使用Python的类方法是最合适的吗?
7 个回答
21
使用 @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)
34
其实,__new__
是一个非常重要的类方法。它是用来创建实例的地方。
所以,当你使用 dict()
时,它实际上是在调用 dict.__new__
,当然了。不过,还有一种很方便的方法可以创建字典,那就是使用类方法 dict.fromkeys()
。
比如:
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
62
初始化的辅助方法:
class MyStream(object):
@classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
@classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...