Python类方法的一个示例用例是什么?

我读过Python中的什么是类方法? 但是这个post中的例子很复杂。 我正在寻找一个Python的classmethods的特定用例的清晰,简单,简单的例子。

你能举出一个小的,具体的例子,Python的classmethod将是正确的工具吗?

Helper方法的初始化:

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): ... 

那么__new__是一个非常重要的分类方法。 实例通常来自哪里

所以dict()当然要调用dict.__new__ ,但是有时候还有另一种方便的方法来制作字典,这就是类方法dict.fromkeys()

例如。

 >>> dict.fromkeys("12345") {'1': None, '3': None, '2': None, '5': None, '4': None} 

我不知道,像命名构造函数的方法?

 class UniqueIdentifier(object): value = 0 def __init__(self, name): self.name = name @classmethod def produce(cls): instance = cls(cls.value) cls.value += 1 return instance class FunkyUniqueIdentifier(UniqueIdentifier): @classmethod def produce(cls): instance = super(FunkyUniqueIdentifier, cls).produce() instance.name = "Funky %s" % instance.name return instance 

用法:

 >>> x = UniqueIdentifier.produce() >>> y = FunkyUniqueIdentifier.produce() >>> x.name 0 >>> y.name Funky 1 

我发现我最经常使用@classmethod将一段代码和一个类关联起来,以避免创build一个全局函数,在这种情况下,我不需要类的实例来使用代码。

例如,如果符合某种模式,我可能会有一个只考虑密钥有效的数据结构。 我可能想要从课内外使用它。 但是,我不想创build另一个全球function:

 def foo_key_is_valid(key): # code for determining validity here return valid 

我宁愿将这些代码与它关联的类分组在一起:

 class Foo(object): @classmethod def is_valid(cls, key): # code for determining validity here return valid def add_key(self, key, val): if not Foo.is_valid(key): raise ValueError() .. # lets me reuse that method without an instance, and signals that # the code is closely-associated with the Foo class Foo.is_valid('my key') 

使用@classmethod的最大原因是在一个备用的构造函数中,这个构造函数是用来inheritance的。 这在多态性中可能非常有用。 一个例子:

 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的类from_square ,因为Shape没有真正定义,它并不知道如何从Square派生出来,因此它只是返回类的默认实例。

inheritance的类然后被允许定义它们自己的这个方法的版本:

 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) 

答案是,你可以,但是你没有得到inheritance的好处,因为Circle必须在方法中显式调用。 也就是说,如果我从一个inheritance的类中调用它而不覆盖,那么每次我都会得到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定义@classmethod ,它将使用Shape.from_square的逻辑,同时保留谁是cls ,并返回适当的形状。

 square = Square(3) for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon): this_shape = polymorphic_class.from_square(square) 
 in class MyClass(object): ''' classdocs ''' obj=0 x=classmethod def __init__(self): ''' Constructor ''' self.nom='lamaizi' self.prenom='anas' self.age=21 self.ville='Casablanca' if __name__: ob=MyClass() print(ob.nom) print(ob.prenom) print(ob.age) print(ob.ville)