我有两个属性,其中包含列表.每当此列表中的任何项目发生更改时,我希望其他列表自行更新.这包括声明obj.myProp[3]=5
.现在,这个语句调用getter函数获取整个列表,从列表中获取第三个项目,并将其设置为5. myProp
列表已更改,但第二个列表永远不会更新.
class Grid(object):
def __init__(self,width=0,height=0):
# Make self._rows a multi dimensional array
# with it's size width * height
self._rows=[[None] * height for i in xrange(width)]
# Make `self._columns` a multi dimensional array
# with it's size height * width
self._columns=[[None] * width for i in xrange(height)]
@property
def rows(self):
# Getting the rows of the array
return self._rows
@rows.setter
def rows(self, value):
# When the rows are changed, the columns are updated
self._rows=value
self._columns=self._flip(value)
@property
def columns(self):
# Getting the columns of the array
return self._columns
@columns.setter
def columns(self, value):
# When the columns are changed, the rows are updated
self._columns = value
self._rows = self._flip(value)
@staticmethod
def _flip(args):
# This flips the array
ans=[[None] * len(args) for i in xrange(len(args[0]))]
for x in range(len(args)):
for y in range(len(args[0])):
ans[y][x] = args[x][y]
return ans
Run Code Online (Sandbox Code Playgroud)
示例运行:
>>> foo=grid(3,2)
>>> foo.rows
[[None, None], [None, None], [None, None]]
>>> foo.columns
[[None, None, None], [None, None, None]]
>>> foo.rows=[[1,2,3],[10,20,30]]
>>> foo.rows
[[1, 2, 3], [10, 20, 30]]
>>> foo.columns
[[1, 10], [2, 20], [3, 30]]
>>> foo.rows[0][0]=3
>>> foo.rows
[[3, 2, 3], [10, 20, 30]]
>>> foo.columns
[[1, 10], [2, 20], [3, 30]]
Run Code Online (Sandbox Code Playgroud)
如果查看最后三行,这就是实际问题发生的地方.我将子列表的第一项设置为三,但从foo.columns
不更新自己将3放在其列表中.
简而言之,我如何创建一个始终更新另一个变量的变量,即使它的子项目正在被更改?
我正在使用Python 2.7
你的问题是你没有设置 foo.rows
违规行 - 你得到它,然后修改其中一个成员.这不会解雇二传手.使用您提出的API,您需要返回一个包含getter和setter的列表.
您最好不要使用rows和columns属性来设置条目,并添加如下__getitem__
方法:
class Grid(object):
def __init__(self, width=0, height=0):
self._data = [None] * width * height;
self.width = width
self.height = height
def __getitem__(self, pos):
if type(pos) != tuple or len(pos) != 2:
raise IndexError('Index must be a tuple of length 2')
x, y = pos
if 0 <= x < self.width and 0 <= y < self.height:
return self._data[x + self.width * y]
else:
raise IndexError('Grid index out of range')
def __setitem__(self, pos, value):
if type(pos) != tuple or len(pos) != 2:
raise IndexError('Index must be a tuple of length 2')
x, y = pos
if 0 <= x < self.width and 0 <= y < self.height:
self._data[x + self.width * y] = value
else:
raise IndexError('Grid index out of range')
@property
def columns(self):
return [
[self[x, y] for x in xrange(self.width)]
for y in xrange(self.height)
]
@property
def rows(self):
return [
[self[x, y] for y in xrange(self.height)]
for x in xrange(self.width)
]
Run Code Online (Sandbox Code Playgroud)
然后虚线变为:
foo[0, 0] = 3
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3799 次 |
最近记录: |