何时使用静态方法和类方法

3

我知道关于这个主题有很多话题,我看了很多。然而,当何时适当使用静态和类方法代替实例方法仍然令我感到困惑。

在我的例子中,我正在为autodesk程序maya制作一个脚本。其中一个模块有一个包含生成对象的方法的类,如下所示:

class Curves(object):
    """Contains methods to generate curves
    """
    @classmethod
    def circle_crv(cls):
        name = mc.circle( nr=(0, 1, 0), c=(0, 0, 0), r=0.5 )
        mc.delete(name, ch=True)
        mc.addAttr(name[0], ln='crvType', dt='string', h=True)
        mc.setAttr(name[0]+'.crvType', 'circle_crv', typ='string', l=True)
        return name[0]

然而,这些方法永远不会被外部模块直接访问。我通过一个字典运行所有这些方法,该字典由外部模块访问(首先搜索外部用户字典),如下所示:

def curve_lib(self, crvtype):
        """Creates a specified curve at origin

        Args:
        crvtype (str): a key to call a function to generate a curve at the
            origin
        """
        userlib = self.usercurve_lib()

        curves_dic = {
            'bendjoint_crv' : self.bendjoint_crv,
            'circle_crv' : self.circle_crv,
            'circlearrow_crv' : self.circlearrow_crv,
            'connectjoint_crv' : self.connectjoint_crv,
            'fktext_crv' : self.fktext_crv,
            'joint_crv' : self.joint_crv,
            'iktext_crv' : self.iktext_crv,
            'cube_crv' : self.cube_crv,
            'quadarrow01_crv' : self.quadarrow01_crv,
            'quadarrow02_crv' : self.quadarrow02_crv,
            'quadarrow03_crv' : self.quadarrow03_crv,
            'quadarrow04_crv' : self.quadarrow04_crv,
            'rootjoint_crv' : self.rootjoint_crv,
            'square_crv' : self.square_crv,
            'switch_crv' : self.switch_crv,
            'triangle_crv' : self.triangle_crv
        }

        if crvtype in userlib:
            name = self.usercurve_lib(crvtype)
        elif crvtype in curves_dic:
            name = curves_dic[crvtype]()
        else:
           raise NameError('Key "%s" not found' %(crvtype))
        return name

首先的问题是,如果该方法从未从类或模块之外访问过,那么它需要成为一个实例吗?在这种情况下,静态方法或类方法是否合适,因为我不需要此方法的单独实例,它只完成一件事情,并且永远不会更改大小或形状,稍后进行调整。
其次,如果我在类中有一个执行简单计算的方法,例如下面所示,那么静态方法是否适合?由于它只是接受输入并每次输出一个单个值,是否有任何理由使其成为实例?
class Vectors(object):
    """Contains methods for various vector math functions
    """

    @staticmethod
    def pointLineDist(vec_a, vec_b, vec_c):
        """The distance between the line ab and the point c.

        Args:
        vec_a (float list): First vector to find distance of.
        vec_b (float list): Second vector to find distance of.
        vec_c (float list): Third vector to find distance of.
        """
        ab = dt.Vector(vec_b) - dt.Vector(vec_a)
        ac = dt.Vector(vec_c) - dt.Vector(vec_a)
        length = dt.length(dt.cross(ab, ac)) / dt.length(ab)

        return length

最后,我知道很多人在这种情况下会说,这些东西根本不应该出现在课堂上,或者类似的话,但这是我想要的方式,我只是想更深入地了解何时使用这些类型的方法。

1个回答

2
简单来说,实例是一个实体,类是该实体的概念。比如,如果你有一个类叫做“人类”,那么一个实例就是一个人,而“人类”这个类对应于人类的概念。例如,测量一个人产生的污染水平是没有意义的,测量人类所产生的污染才更有意义。因此,如果你有一个名为“measureGeneratedPollution”的方法,它应该是静态的。然而,如果你有一个名为“breath”的方法,那么这是一个个体行为,所以“breath”应该是一个实例级别的方法。实例级别与静态级别本质上类似于个体行为与集体行为。
让我们看另一个成员的例子。考虑鸟类这个类。鸟类总体上没有颜色,因此颜色应该是实例级别的成员。然而,birdCount是一个集体信息,因此它应该是静态的。
请记住,对于成员/方法,级别(实例或类级别)不是由可访问性确定的,而是由拥有属性或执行操作的主体确定的。因此,当您制定这样的计划时,请将句子逻辑写下来,直到您变得更加专业。例如:
“鸟有颜色。”
“有一定数量的鸟。”
向自己提问:
“谁有颜色? -> 鸟 -> 单数 -> 实例”
“谁拥有数量? -> 鸟 -> 复数 -> 集体 -> 静态”

非常有帮助!但是,类方法与实例方法是否由可访问性决定?比如说我有一个鸟类,其中有一个颜色方法,但是这个方法只在类内被另一个实例方法使用。这样做将更有意义成为一个类方法吗? - Neo Conker
不,这不是我们应该表达的方式。真正的问题是:方法是个体的还是集体的。例如:一个人类实例有一个sex()方法。sex()不是一个集体行为(至少希望如此),并且该人的sex方法是私有的,其他人类实例不应该能够调用当前个体的sex()方法。所以,sex()是私有的和实例级别的。因此,问题不在于公开级别,而在于方法/成员的个体性或集体性。 - Lajos Arpad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接