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


68

我已经阅读了Python中的Class方法什么用?但是这篇文章中的例子很复杂。我正在寻找一个清晰,简单,准系统的Python类方法用例的例子。

您能否列举一个小的特定示例用例,其中Python类方法将是完成此工作的正确工具?



1
我已经编辑了问题以解释两个问题之间的区别。我正在寻找Hello World类型的裸露示例用例。
咖啡研磨机

Answers:


55

初始化的辅助方法:

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

6
实际上,提供备用构造函数是的经典用例classmethod。与它们的staticmethod等效项不同,它们在子类中表现良好。
ncoghlan 2011年

31

好吧,这__new__是一个非常重要的类方法。通常是实例来自的地方

所以dict()通话dict.__new__,当然,但有使http://stardict.sourceforge.net/Dictionaries.php下载有时这是类方法另一个方便的方法dict.fromkeys()

例如。

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

1
+1是一个很好的真实示例。尽管您隐含了这fromkeys也是一个类方法的事实。
senderle'4

1
从技术上讲,__new__是隐式地转换为静态方法。实例创建过程中还有其他机制将适当的类对象作为第一个参数传递。dict.fromkeys但是,它是实际的类方法的一个很好的例子。
ncoghlan 2011年

而且,当然,__new__仍然依赖于相同的概念,因为classmethod即使没有实际实施的方式。
ncoghlan 2011年

20

我不知道,诸如命名构造方法之类的东西?

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

13

使用a的最大原因@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尚未真正定义,因此它并不真正知道如何从a派生自身,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)

您可能会说这一切都很好,但我为什么不能仅仅使用as@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)

您在RightTriangle类中有错字。init方法应为“ init ”,但您将其编写为“ __init”
lone_coder

10

我发现我最常用于@classmethod将一段代码与一个类相关联,以避免在不需要该类实例使用代码的情况下创建全局函数。

例如,我可能有一个数据结构,该数据结构仅在符合某种模式的情况下才认为键是有效的。我可能想在课堂内外使用它。但是,我不想创建另一个全局函数:

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')

1
类方法可以用一个类或实例调用,因此,例如在add_key Foo.is_valid(key) 可能self.is_valid(key) docs.python.org/library/functions.html#classmethod
cerberos

19
这种用例听起来更像是静态方法,而不是类方法。如果您的方法未使用cls参数,则应该使用@staticmethod代替。
吉姆·丹尼斯

-4
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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.