Python 中二元函数的正确模式
Proper pattern for dyadic functions in Python
我有一个 Python 程序,它有一个问题,我的头因范围规则而旋转。
假设我们有一个名为 Matrix 的 class。在内部,它包含二维数字射线。所以实例化它的核心看起来像:
z = Matrix([values])
所以实例 z 获取列表的列表并创建一个实例,其中 z.internal_matrix 是一个属性,其中包含传入的类似矩阵的列表。
我总是被困住的问题是:如果你正在构建像 "matrix_mult"?
这样的二元函数,你如何构建代码以使其具有最大的可靠性和清晰度
注意当你要调用的函数是一个变量的函数时,这个问题较少出现。如果是这样,在代码中我们可以有一个像 "determinant" 这样的函数,它是 monadic 并且引用 self。所以,我认为我们更喜欢
z.determinant()
行列式是在class内部声明的函数(与init相同)。
现在假设我们有一个像乘法这样的二元函数,叫做 'matrix_multiply'。我们可以将其定义在与 init 相同的级别。
现在语法变得有点谨慎 - 表明 'calling instance' 在某种意义上对其数据更有特权 - 因为我们可能会这样做
z = self.matrix_multiply(y)
其中 y 是同一 class 的另一个对象。我们也可以做得同样好:
z = y.matrix_multiply((x))
最后,可以在 maxtrix_multiply 的某个级别创建函数。它将了解所有 class 内部结构、数据和方法。然后我们可以写:
z = matrix_multiply(x, y)
其中 matrix_multiply 可以是 class 的成员(方法),或者它可以像 FORTRAN 子程序一样独立;它只需要知道如何通过 "reaching into" 对象框和访问内部例程来实例化一个新变量。这样做可以清楚地表明它不是 class 或 class 实例内部的 "magic" 函数。
但是,要工作,matrix_multiply 必须对 class/instance 变量有透彻的了解,这样它才能对任何实例施展魔法 "outside"。
试图考虑所有的可能性 - 并让其中一个发挥作用 - 正在耗尽我的大脑。在这种情况下一般的建议是什么?
我可能会在 Matrix
class 上选择一个名为 multiply
的 classmethod
。它会被称为 z = Matrix.multiply(x, y)
。这样就避免了任何关于其中一个操作数是 "more privileged" 的建议,并将与 Matrix
class 内部相关的所有逻辑保留在 Matrix
class 中.
class Matrix:
def __init__(self, values):
...
@classmethod
def multiply(cls, left: 'Matrix', right: 'Matrix') -> 'Matrix':
...
return result
然而,这是在不知道您的 project/application. 的任何其他上下文的情况下,例如,如果代码看起来可能在您的应用程序中更有意义喜欢
z = x.multiply(y)
在这种情况下,您应该将其作为 Matrix
class.
上的常规方法来实现
最后,如果你想能够写
z = x * y
那么你需要在Matrix
上实现__mul__
方法 class:
class Matrix:
...
def __mul__(self, other: 'Matrix') -> 'Matrix':
...
return result
我有一个 Python 程序,它有一个问题,我的头因范围规则而旋转。
假设我们有一个名为 Matrix 的 class。在内部,它包含二维数字射线。所以实例化它的核心看起来像:
z = Matrix([values])
所以实例 z 获取列表的列表并创建一个实例,其中 z.internal_matrix 是一个属性,其中包含传入的类似矩阵的列表。
我总是被困住的问题是:如果你正在构建像 "matrix_mult"?
这样的二元函数,你如何构建代码以使其具有最大的可靠性和清晰度注意当你要调用的函数是一个变量的函数时,这个问题较少出现。如果是这样,在代码中我们可以有一个像 "determinant" 这样的函数,它是 monadic 并且引用 self。所以,我认为我们更喜欢
z.determinant()
行列式是在class内部声明的函数(与init相同)。
现在假设我们有一个像乘法这样的二元函数,叫做 'matrix_multiply'。我们可以将其定义在与 init 相同的级别。
现在语法变得有点谨慎 - 表明 'calling instance' 在某种意义上对其数据更有特权 - 因为我们可能会这样做
z = self.matrix_multiply(y)
其中 y 是同一 class 的另一个对象。我们也可以做得同样好:
z = y.matrix_multiply((x))
最后,可以在 maxtrix_multiply 的某个级别创建函数。它将了解所有 class 内部结构、数据和方法。然后我们可以写:
z = matrix_multiply(x, y)
其中 matrix_multiply 可以是 class 的成员(方法),或者它可以像 FORTRAN 子程序一样独立;它只需要知道如何通过 "reaching into" 对象框和访问内部例程来实例化一个新变量。这样做可以清楚地表明它不是 class 或 class 实例内部的 "magic" 函数。
但是,要工作,matrix_multiply 必须对 class/instance 变量有透彻的了解,这样它才能对任何实例施展魔法 "outside"。
试图考虑所有的可能性 - 并让其中一个发挥作用 - 正在耗尽我的大脑。在这种情况下一般的建议是什么?
我可能会在 Matrix
class 上选择一个名为 multiply
的 classmethod
。它会被称为 z = Matrix.multiply(x, y)
。这样就避免了任何关于其中一个操作数是 "more privileged" 的建议,并将与 Matrix
class 内部相关的所有逻辑保留在 Matrix
class 中.
class Matrix:
def __init__(self, values):
...
@classmethod
def multiply(cls, left: 'Matrix', right: 'Matrix') -> 'Matrix':
...
return result
然而,这是在不知道您的 project/application. 的任何其他上下文的情况下,例如,如果代码看起来可能在您的应用程序中更有意义喜欢
z = x.multiply(y)
在这种情况下,您应该将其作为 Matrix
class.
最后,如果你想能够写
z = x * y
那么你需要在Matrix
上实现__mul__
方法 class:
class Matrix:
...
def __mul__(self, other: 'Matrix') -> 'Matrix':
...
return result