【问题标题】:In Python, is what are the differences between a method outside a class definition, or a method in it using staticmethod?在 Python 中,类定义之外的方法与使用静态方法的方法之间有什么区别?
【发布时间】:2020-05-02 00:55:36
【问题描述】:

我一直在进行一组非常密集的计算。这一切都是为了支持我遇到的特定问题。

但问题的性质与此没有什么不同。假设我开发了一个名为“Matrix”的类,它具有实现矩阵的机制。实例化可能会采用列表列表,这将是矩阵条目。

现在我想提供一个乘法方法。我有两个选择。首先,我可以像这样定义一个方法:

class Matrix():
    def __init__(self, entries)
    # do the obvious here
    return

    def determinant(self):
        # again, do the obvious here
        return result_of_calcs

    def multiply(self, b):
        # again do the obvious here
        return

如果我这样做,两个矩阵对象 a 和 b 的调用签名是

a.multiply(b)...

另一个选择是@staticmethod。然后,定义如下:

    @staticethod
    def multiply(a,b):
    # do the obvious thing.

现在调用签名是:

z = multiply(a,b)

我不清楚什么时候一个比另一个好。独立函数并不是真正的类定义的一部分,但谁在乎呢?它完成了工作,并且因为 Python 允许从外部“进入对象”引用,它似乎可以做任何事情。在实践中,它们(类和方法)最终会出现在同一个模块中,因此它们至少在那里链接。

另一方面,我对@staticmethod 方法的理解是,该函数现在是类定义的一部分(它定义了其中一个方法),但是该方法没有传入“self”。在某种程度上,这很好,因为调用签名更好看:

z = multiply(a,b)

并且该函数可以访问所有实例的方法和属性。

这是查看它的正确方法吗?是否有充分的理由去做其中之一?它们在哪些方面不等效?

【问题讨论】:

    标签: python-3.x static-methods


    【解决方案1】:

    自从回答这个问题以来,我已经做了很多 Python 编程。

    假设我们有一个名为 matrix.py 的文件,它有一堆用于操作矩阵的代码。我们想提供一个矩阵乘法。

    这两种方法是:

    1. 使用签名 multiply(x,y) 定义一个独立的函数
    2. 使其成为所有矩阵的方法:x.multiply(y)

    矩阵乘法就是我所说的二元函数。换句话说,它总是需要两个参数。

    诱惑是使用#2,以便矩阵对象“随处携带”乘法的能力。然而,与它相乘唯一有意义的是另一个矩阵对象。在这种情况下,有两种同样好的方法可以做到这一点,即: z=x.multiply(y) 或者 z=y.multiply(x)

    但是,更好的方法是在文件中定义一个函数:

        multiply(x,y)
    

    multiply() 因此,是任何使用“库”的代码都期望可用的函数。它不需要与每个矩阵相关联。而且,由于用户将执行“导入”,他们将获得乘法方法。这是更好的代码。

    我错误地混淆了两件事,导致我找到了附加到每个对象实例的方法:

    1. 需要在文件中普遍可用的函数 暴露在外面;和
    2. 仅在文件内部需要的函数。

    multiply() 是类型 1 的示例。任何矩阵“库”都应该定义矩阵乘法。

    我担心的是需要公开所有“内部”功能。例如,假设我们要使外部可用的矩阵 add()、multiple() 和 invert()。然而,假设我们不想让外部可用——但内部需要——determinant()。

    “保护”用户的一种方法是在矩阵的类声明中将行列式设为函数(def 语句)。然后保护它免受暴露。但是,如果他们知道内部结构,没有什么能阻止代码用户通过使用方法 matrix.determinant() 进行访问。

    最后,很大程度上归结为惯例。公开一个接受两个矩阵的矩阵乘法函数更有意义,它被称为乘法(x,y)。至于行列式函数,与其将其“包装”在类中,不如将其定义为 __determinant(x) 与矩阵的类定义处于同一级别。

    您似乎永远无法通过声明来真正保护内部方法。您能做的最好的事情就是警告用户。 “dunder”方法给出警告“这不应该在这个文件中的代码之外被调用”。

    【讨论】:

      猜你喜欢
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 2016-02-03
      • 2012-11-02
      • 2011-07-11
      • 1970-01-01
      • 2011-04-23
      相关资源
      最近更新 更多