如何使用一个类来存储在不同函数中更新的变量,然后在不同的函数中调用这些更新的变量?

Posted

技术标签:

【中文标题】如何使用一个类来存储在不同函数中更新的变量,然后在不同的函数中调用这些更新的变量?【英文标题】:How to use a class to store variables that are updated in different functions, and then call these updated variables in different functions? 【发布时间】:2022-01-23 14:34:44 【问题描述】:

我正在解决一个涉及遍历n x m matrix之字形方式的问题,其中n and m可以是相同的数字或不同的数字,即我们将有正方形或矩形矩阵

为了解决这个问题,我有一个ma​​in方法,它会遍历矩阵;在这个主方法中,我创建并调用moveDiagonallyUpwardsmoveDiagonallyDownwards 方法以曲折的方式移动。

我遇到的问题是,当我将 rowcol 作为参数从 main 方法传递给这两个其他方法时,在这些方法中我更新 row 和 col,例如+=1 或 -= 1。 当我返回主方法时,这些更改不会反映在主方法中。我也明白为什么会这样。

所以我的挑战是,如何将更新后的rowcol 传回主方法?我想过使用global class 来实现上述目的。 我的想法是创建一个单独的类来保存这些变量,如下所示,但我在 ma​​in 方法中调用和使用这些 global row and col 时遇到问题。

任何想法如何调整 ma​​in 方法 中的row and col 以实现上述目标?谢谢!

array = [
    [1, 3, 4, 10],
    [2, 5, 9, 11],
    [6, 8, 12, 15],
    [7, 13, 14, 16]
  ]

class matrixMovement: 
    def __init__(self,row=0,col=0,output=[]): 
        self.row = row
        self.col = col
        self.output = output
#Main Method
def zigzagTraverse(array):
    output.append(array[row][col])
    while array.row<= len(array)-1 or array.col<= len(array[0])-1: 
        if array.row< len(array)-1: 
            array.row += 1
            output.append(array[row][col])
            diagonalUp(row,col,array,output)
        if col < len(array[0])-1: 
            col += 1
            output.append(array[row][col])
            diagonalDown(row,col,array,output)
    return output
            
def diagonalUp(row,col,array,output): 
    while row > 0 and col< len(array[0])-1: 
        row -= 1
        col += 1
        output.append(array[row][col])
    return matrixMovemenet(row,col,output)
    
def diagonalDown(row,col,array,output): 
    while row<len(array)-1 and col > 0: 
        col-= 1
        row += 1
        output.append(array[row][col])
    return matrixMovemenet(row,col,output)

【问题讨论】:

传递给zigzagTraversearray是什么? 让我补充问题 【参考方案1】:

你有几个问题。一是局部范围。另一种是使用return 语句,但对返回的对象不做任何事情。

有几种方法可以解决这个问题。一种是忽略局部变量,只从matrixMovement 创建一个对象,并利用它是可变的这一事实。

class MatrixMovement: 
    def __init__(self, row=0, col=0, output=None):
        # I modified this to avoid the mutable default
        if output is None:
            output = []
        self.row = row
        self.col = col
        self.output = output


# Main Method
def zigzag_traverse(array):
    # this is the object we will be mutating
    obj = MatrixMovement()
    obj.output.append(array[obj.row][obj.col])
    while obj.row <= len(array) - 1 or obj.col <= len(array[0]) - 1: 
        if obj.row < len(array) - 1: 
            obj.row += 1
            obj.output.append(array[obj.row][obj.col])
            diagonal_up(obj, array)
        if obj.col < len(array[0]) - 1: 
            obj.col += 1
            obj.output.append(array[obj.row][obj.col])
            diagonal_down(obj, array)
        # without this condition the loop will never break
        if obj.row == len(array) - 1 and obj.col == len(array[0]) - 1:
            break
    return obj.output


def diagonal_up(obj, array):
    # since we are passing in a mutable object
    # anything attribute we change on it
    # will be reflected on the object from the call site
    while obj.row > 0 and obj.col < len(array[0]) - 1: 
        obj.row -= 1
        obj.col += 1
        obj.output.append(array[obj.row][obj.col])


def diagonal_down(obj, array):
    # the same rules as diagonal_up
    while obj.row < len(array) - 1 and obj.col > 0: 
        obj.col -= 1
        obj.row += 1
        obj.output.append(array[obj.row][obj.col])

【讨论】:

太简洁了!这就是我想这样做的方式,但我在想如何在整个代码中写一百万次 matrixMovement,所以当你做 obj= matrixMovement;这很有帮助! - 因为我不知道你能做到这一点。 我也知道引用,我知道你是如何引用 obj 的。一切,这使得。我可以问 - 为什么在初始化输出时做一个 if 语句?我不能在参数中将其初始化为 output = [] 吗? 你可以,但如果你不带参数调用它,它会为每个后续调用使用相同的[]。请参阅this question 以获得更好的解释。 我应该提到我实际上并没有测试基本代码本身是否有错误。我只是将其更改为您期望的行为方式。 好的,为了确保我从链接中理解正确,通过输出 = [] 将是一个问题 - 如链接中所述 - 只有当我们在没有参数的情况下调用它?不然就好了?【参考方案2】:

在解决了我在您的遍历中发现的一些错误之后,我选择使用文档、边界检查来编写此代码。

解释是用 cmets 写的。有什么不懂的欢迎追问。

from typing import TypeVar, Sequence, TypeAlias

from dataclasses import dataclass

_T = TypeVar("_T")

MatrixType = Sequence[Sequence[_T]]

@dataclass
class Point:
    row: int
    col: int

def zigzag_traverse(matrix: MatrixType[_T]) -> list[_T]:
    output: list[_T] = []

    row_length = len(matrix[0])
    if any(len(row) != row_length for row in matrix):
        raise ValueError("Matrix is not rectangular.")
    
    # Initialize.
    boundry = Point(len(matrix) - 1, row_length - 1)
    
    if boundry.row < 0 or boundry.col < 0:
        return output  # Matrix is empty.

    pointer = Point(0, 0)


    # Start traversing.

    output.append(matrix[pointer.row][pointer.col])
    
    
    while pointer != boundry:

        # Go right until edge, then start moving down.
        if pointer.col < boundry.col:
            pointer.col += 1
        else:
            pointer.row += 1

        output.extend(_diagonal_left_down(pointer, matrix))

        # We reached the boundry, stop traversing.
        if pointer == boundry:
            break

        # Go down until edge, then start moving right.
        if pointer.row < boundry.row:
            pointer.row += 1
        else:
            pointer.col += 1

        output.extend(_diagonal_right_up(pointer, matrix))
    
    return output

def _diagonal_left_down(pointer: Point, matrix: MatrixType[_T]) -> list[_T]:
    """Traverse left-down diagonal.
    
    Args:
        pointer: The current position. Will be modified.
        matrix: The matrix to move over.
    
    Returns:
        The list of elements traversed.
    """
    row, col = pointer.row, pointer.col
    output = []

    while row < len(matrix) - 1 and col > 0:
        output.append(matrix[row][col])
        row += 1
        col -= 1
    
    # Reached the edge
    output.append(matrix[row][col])
    pointer.row, pointer.col = row, col

    return output

def _diagonal_right_up(pointer: Point, matrix: MatrixType[_T]) -> list[_T]:
    """Traverse right-up diagonal.
    
    Args:
        pointer: The current position. Will be modified.
        matrix: The matrix to move over.
    
    Returns:
        The list of elements traversed.
    """
    row, col = pointer.row, pointer.col
    output = []

    while row > 0 and col < len(matrix[0]) - 1:
        output.append(matrix[row][col])
        row -= 1
        col += 1
    
    # Reached the edge
    output.append(matrix[row][col])
    pointer.row, pointer.col = row, col

    return output

【讨论】:

以上是关于如何使用一个类来存储在不同函数中更新的变量,然后在不同的函数中调用这些更新的变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SheetView 函数调用更新 ContentView 中的变量?

C++线程更新变量问题

如何在 Python 中将大量变量传入和传出函数?

如何在缓存结果时更新非局部变量?

如何在 Postgres 函数中存储日期变量?

如何确保在不同线程读取变量之前将变量存储到内存中[关闭]