【问题标题】:Should I use the class name or `cls` param to construct a an instance?我应该使用类名还是 `cls` 参数来构造一个实例?
【发布时间】:2017-09-09 08:53:28
【问题描述】:

如标题所述,我以一个困惑为例:

class Point(object):

    def __init__(self, x=0.0, y=0.0):
        self.x, self.y = x, y

    @classmethod
    def get_point1(cls, cor): # cor is list with x=1 and y=2
        return Point(cor[0], cor[1])

    @classmethod
    def get_point2(cls, cor):
        return cls(cor[0], cor[1])

我很困惑我应该使用哪一个(get_point1get_point2),它们之间有什么区别?

【问题讨论】:

  • 想一想如果您将Point 子类化并在子类上调用这些方法中的每一个会发生什么。您应该使用哪种取决于您想要的行为。
  • cls() 是首选,因为它允许您扩展该类。例如,class SpecialPoint(Point): pass。目前,SpecialPoint.get_point1(cor) 将创建一个Point 对象,而SpecialPoint.get_point2(cor) 将创建一个SpecialPoint
  • 谢谢,除了子类还有其他区别吗?
  • 一个可能是,如果您将来最终更改类的名称,您只需更改一次(在顶部),而不是在每个类方法中。
  • cls() 如果你要继承 Point 绝对是有意义的。如果您认为最终可能将其子类化,这可能是有道理的。如果这两种情况都不是,那么使用Point() 会更加明确和易读。

标签: python


【解决方案1】:

@classmethod 装饰器使函数成为类方法,而不是实例方法。为了使其更健壮,最好使用cls 而不是定义它的实际类名。

如果您使用 cls,将传递的参数取决于在显式使用 Point 时被调用的实际类(例如,如果您将 Point 子类化),可能如果您将其子类化并使用类方法,则会导致问题。

以这段代码为例

class Point(object):

    def __init__(self, x=0.0, y=0.0):
        self.x, self.y = x, y

    @classmethod
    def get_point1(cls, cor): # cor is list like [1,2] with x=1 and y=2
        return Point(cor[0], cor[1])

    @classmethod
    def get_point2(cls, cor):
        return cls(cor[0], cor[1])


class SubPoint(Point):
    pass


sub1 = SubPoint.get_point1([0, 1])
sub2 = SubPoint.get_point2([2, 2])

print sub1.__class__
print sub2.__class__

<class '__main__.Point'>
<class '__main__.SubPoint'>

还有其他区别吗? - 好吧,如果您需要在类方法中执行一些逻辑,这取决于类属性,那么可以。

【讨论】:

    猜你喜欢
    • 2017-12-22
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 2021-02-03
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    相关资源
    最近更新 更多