分配变量= self创建副本。需要它作为参考(指针)

问题描述 投票:-1回答:1

我正在为我的作业创建一个矩阵类,通常如果我将变量指定为x = self,x是对self的引用,因此所有操作都已到位。我有一个减少矩阵的函数,作为一个可选参数,我添加了inplace=False,这样:

if inplace:
    self = A
else: 
    A = self.copy()

现在通常当我这样做时,如果我要进行像A += B这样的操作,那么self就会被修改。但是,当我运行A.reduce(inplace=True)时,A没有被修改。我已经在下面列出了全班,我希望有人可以告诉我为什么操作没有到位。提前致谢。

import numpy as np

class matrix:
    def __init__(self, A):
        self.value = np.array(A, dtype=np.float)
        self.indices = np.arange(self.value.shape[0])
        self.shape = self.value.shape

    def swap_rows(self, r1, r2):
        ind = np.arange(self.value.shape[0])
        swap = (r1, r2)
        ind[swap[0]] = swap[1]
        ind[swap[1]] = swap[0]
        temp_ind = self.indices[swap[0]]
        self.indices[swap[0]] = self.indices[swap[1]]
        self.indices[swap[1]] = temp_ind
        self.value = self.value[ind]

    def add_rows(self, operations):
        # operations = [(c, row1, row2)]
        # where operation will be:
        # c * row1 + row2 -> row2
        for c, row1, row2 in operations:
            self.value[row2] += c * self.value[row1]

    # ... #           

    def reduce(self, b_ = None, swap=True, normalize=True, return_steps=False, inplace=False, debug=False):
        if inplace:
            A = self
        else:
            A = self.copy()
        if b_:
            b = b_.copy()
            if len(b.shape) == 1:
                b.reshape((-1, 1), inplace=True)
        if return_steps:
            steps = []
        # Normalize
        if normalize:
            A_max = A.row_max()
            A /= A_max
            if debug:
                print("A after normalization:")
                print(A)
                print("")
            if return_steps:
                steps.append([('normalize', A_max)])
            if b_:
                b /= A_max
        m, n = A.shape
        for col in range(n-1):
            # Swap
            if swap:
                # Check for max value
                max_ind = np.argmax(np.abs(A[:, col]))
                # Check if max is zero
                if np.abs(A[max_ind, col]) < 1e-30:
                    print('Matrix is singular')
                    if b_:
                        return A, b
                    else:
                        return A
                # Swap if necessary
                if max_ind > col:
                    A.swap_rows(col, max_ind)
                    if return_steps:
                        steps.append([('swap', col, max_ind)])
                    if b_:
                        b.swap_rows(col, max_ind)
            # Get constants
            cs = -A[col+1:, col] / A[col, col]
            operations = [(c, col, i+col+1) for i, c in enumerate(cs)]
            if return_steps:
                steps.append(operations)
            A.add_rows(operations)
            if b_:
                b.add_rows(operations)
        if debug:
            print("A after row operations:")
            print(A)
            print("")
        return_vals = np.array([A, None, None])
        if b_:
            return_vals[1] = b
        if return_steps:
            return_vals[2] = steps
        if inplace:
            return_vals = return_vals[1:]
        if return_vals.any():
            return tuple(return_vals[return_vals != None])

    # ... #

    def row_max(self):
        return np.array([self[row, i] for row, i in enumerate(np.argmax(np.abs(self.value), axis=1))]).reshape(-1, 1)

    # ... #

    def copy(self):
        return matrix(np.copy(self.value))

    def T(self):
        return matrix(self.value.T)

    def inverse(self):
        return matrix(np.linalg.inv(self.value))

    def flip(self, axis=None, inplace=False):
        if inplace:
            self.value = np.flip(self.value, axis=axis)
        else:
            return matrix(np.flip(self.value, axis=axis))

    def reshape(self, shape, inplace=False):
        if inplace:
            self.value = self.value.reshape(*shape)
        else:
            return matrix(self.value.reshape(*shape))

    def __add__(self, x):
        if isinstance(x, matrix):
            return matrix(self.value + x.value)
        else:
            return matrix(self.value + x)

    def __sub__(self, x):
        if isinstance(x, matrix):
            return matrix(self.value - x.value)
        else:
            return matrix(self.value - x)

    def __mul__(self, x):
        if isinstance(x, matrix):
            return matrix(self.value * x.value)
        else:
            return matrix(self.value * x)

    def __truediv__(self, x):
        if isinstance(x, matrix):
            return matrix(self.value / x.value)
        else:
            return matrix(self.value / x)

    # ... #

    def __matmul__(self, A):
        if isinstance(A, matrix):
            return matrix(self.value @ A.value)
        else:
            return matrix(self.value @ A)

    def __repr__(self):
        return str(self.value)

    def __getitem__(self, item):
        return self.value[item]

    def __setitem__(self, i, v):
        self.value[i] = v


A = matrix([ [ 5,  6,  7,  5, -1],
             [ 8, -4, -1,  0, -3],
             [ 2,  1, -1,  3,  6],
             [-9, 10,  1, -4,  6],
             [ 9,  5, -5, -8,  4] ])

print("Original A:")
print(A)
print("")   
A.reduce(inplace=True, debug=True)
print("A after inplace reduce function:")
print(A)
print("")

EDIT

以下是我试图以简单的方式重新创建的内容:

class obj:
    def __init__(self, value):
        self.value = value

    def copy(self):
        return obj(self.value)

    def op(self, y, inplace=False):
        if inplace:
            x = self
        else:
            x = self.copy()
        x.value += y
        x.value /= y
        if not inplace:
            return x

    def __repr__(self):
        return str(self.value)

x = obj(5)
x.op(3)
print("Copy:", x)
x.op(3, inplace=True)
print("Inplace:", x)
python python-3.x class oop ref
1个回答
1
投票

你说像+=这样的运算符会修改对象,但这并不总是正确的。只有在运算符左侧的对象类型具有__iadd__方法时才会发生这种情况。如果它只有__add__方法,则Python解释器将X += Y转换为X = X + Y,这通常不是就地操作。

所以你的代码没有达到预期的原因是因为你没有__itruediv__操作符,当你调用A /= A_max(如果normalizeTrue)时,你会复制,尽管你打算在适当的位置操作。

© www.soinside.com 2019 - 2024. All rights reserved.