如何使用一个类来存储在不同函数中更新的变量,然后在不同的函数中调用这些更新的变量?
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
可以是相同的数字或不同的数字,即我们将有正方形或矩形矩阵。
为了解决这个问题,我有一个main方法,它会遍历矩阵;在这个主方法中,我创建并调用moveDiagonallyUpwards
和moveDiagonallyDownwards
方法以曲折的方式移动。
我遇到的问题是,当我将 row
和 col
作为参数从 main 方法传递给这两个其他方法时,在这些方法中我更新 row 和 col,例如+=1 或 -= 1。
当我返回主方法时,这些更改不会反映在主方法中。我也明白为什么会这样。
所以我的挑战是,如何将更新后的row
和col
传回主方法?我想过使用global class
来实现上述目的。
我的想法是创建一个单独的类来保存这些变量,如下所示,但我在 main 方法中调用和使用这些 global row and col
时遇到问题。
任何想法如何调整 main 方法 中的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)
【问题讨论】:
传递给zigzagTraverse
的array
是什么?
让我补充问题
【参考方案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
【讨论】:
以上是关于如何使用一个类来存储在不同函数中更新的变量,然后在不同的函数中调用这些更新的变量?的主要内容,如果未能解决你的问题,请参考以下文章