免責聲明:我還沒有測試過任何上面的代碼,所以如果有錯誤,我很抱歉。此外,我提出,我們正在談論的Python 3這裏的假設,但我認爲這個代碼應該仍然在Python 2
不正常工作沒有額外的函數調用。
例如,假設你有一個Matrix
類,如下所示:
from copy import copy
class Matrix:
def __init__(self, rows):
self._rows = rows
@property
def rows(self):
return list(map(copy, self._rows))
@rows.setter
def rows(self, rows):
self._rows = list(map(copy, rows))
def cols(self):
return list(map(list, zip(*self._rows)))
@cols.setter
def cols(self, cols):
self._rows = list(map(list, zip(cols)))
def transpose(self):
self.cols = self._rows
變調功能甚至不需要使用列表拆包。但是這仍然使用zip
,你提到你正在考慮廢除。
如果你想使用列表解包,你必須知道有多少值將被解壓縮。因此,如果你支持可變維度,那麼這是一個不行。否則,您必須對更改進行硬編碼。
但還有另一個問題。由於移調會改變非方形矩陣的尺寸,因此不能進行按元素交換。在這種情況下會發生IndexError
。你必須做行或列交換。要做到這一點,你必須在某個時刻製作一個列或行的副本(如上面的代碼所示 - 注意getter副本不是必需的)。
有一種技術可以使用。您可以將多維列表存儲爲一維列表,然後使用數學來確定行(或列)的起始位置。例如,你可以做到以下幾點:
class Matrix:
def __init__(self, values, number_of_columns, number_of_rows):
self._values = values
self._number_of_columns = number_of_columns
self._number_of_rows = number_of_rows
@property
def rows(self):
return [self._values[i * self._number_of_rows:(i + 1) * self._number_of_rows] for i in range(self._number_of_rows)]
@property
def cols(self):
return [self._values[i::self._number_of_columns] for i in range(self._number_of_columns)]
def transpose(self):
for i in range(self._number_of_rows):
self._values[i * self._number_of_rows:(i + 1) * self._number_of_rows], self._values[i::self._number_of_rows] = self._values[i::self._number_of_columns], self._values[i * self._number_of_columns:(i + 1) * self._number_of_columns]
self._number_of_columns, self._number_of_rows = self._number_of_rows, number_of_columns
雖然第一次迭代掉期值他們適當的地方,在一個非方陣,一些值都將丟失。例如,考慮構造如Matrix(list(range(6)), 3, 2)
的矩陣。
每一趟如下:
self._values == [0, 3, 1, 3, 2, 5]
self._values == [0, 3, 3, 2, 2, 5]
注意,它把這些值在第一次傳遞正確的地方。但它會覆蓋尚未移動的值。避免這種情況的唯一方法是複製。所以,你可以改變的transpose
方法的工作方式如下:
def transpose(self):
new_values = []
for i in range(self._number_of_rows):
new_values.extend(self._values[i::self._number_of_columns])
self._values = new_values
self._number_of_columns, self._number_of_rows = self._number_of_rows, number_of_columns
但是,這是非常令人費解和難以調試。所以這個故事的寓意是僅僅使用self.state = list(zip(*self.state))
-它很容易閱讀,很難搞定 - 或者你的方法已經有了。
在第二眼,看來你transpose
方法做了雙重換位。當然,基體M的換位的換位是相同的M.你需要讓天花板內環較小:
def transpose(self):
for i in range(dim):
for j in range(i):
self.state[i][j], self.state[j][i] = self.state[j][i], self.state[i][j]
return self
這裏有一個配方:https://rosettacode.org/wiki/Matrix_transposition#蟒蛇 – noumenal