2016-05-17 68 views
1

我的程序使用pyplot绘制形状。我选择以非常特别的方式创建形状,因为程序最终将解决this problem。因此,绘制形状的信息包含在我命名为big_shape的数据类型中。 big_shape是一个dicts列表,每个dict包含绘制一个1x1正方形所需的信息,我已经命名了一个unit_square。为什么我的函数在函数范围之外改变它的参数?

在步骤我目前正在与挣扎,我创建了一个功能make_copies()应该做到以下几点:

1. Iterate over each unit_square in a big_shape and run the transpose() function 
    -This should in turn create a new, transposed copy of the unit_square 
2. Compile the new unit_squares into a second big_shape 
3. Combine the new_big_shape with the original to make a third big_shape 
4. Return the third big shape so that everything can be plotted. 

这个问题似乎来自于转置()函数。 I 期望函数获取一个单位平方的输入并将该单位平方的一个副本输出到新位置,而不影响原始单位平方。但是,转置功能似乎正在影响输入单位正方形,使得它最终在转置点中相互绘制原始图像和转置图像。

你能帮我弄清楚为什么转置()函数的行为不如预期?

import matplotlib.pyplot as plt 


def make_unit_square(square_info): 
    ''' 
    A unit square is a 1x1 square. The square_info parameter is a two item list containing coordinates of the square's left top corner 
    point (index [0], given as a list or tuple) and its color (index [1]). make_unit_square returns a dict that will eventually be 
    the information input into a plt.Polygon(). 
    ''' 
    points = [square_info[0],[square_info[0][0]+1,square_info[0][1]],[square_info[0][0]+1,square_info[0][1]-1],[square_info[0][0],square_info[0][1]-1]] 
    return {'type': 'unit square','points': points, 'color': square_info[1]} 



def make_copies(big_shape): 
    ''' 
    A big_shape is a list of unit_squares. Thus, any function taking a parameter big_shape will iterate over the 
    composite unit squares. The make_copies function should iterate over each unit_square in a big_shape and run the 
    transpose() function, which should in turn create a new, transposed copy of the unit_square. These new unit_squares 
    are compiled into a new big_shape, which is then combined with the old big_shape and returned by the make_copies 
    function so that the two can eventually be plotted at once. 
    ''' 
    def transpose(unit_square,xdistance,ydistance): 
     new_unit_square = unit_square 
     new_points = [ [point[0] + xdistance, point[1] + ydistance] for point in unit_square['points']] 
     new_unit_square['points'] = new_points 
     return new_unit_square 


    #iterate over the big_shape, making a new, transposed copy of each of its composit unit_squares. THIS SHOULD LEAVE THE 
    #ORIGINAL BIG SHAPE UNCHANGED, BUT SOMETHING SEEMS TO GO WRONG. 
    new_big_shape = [transpose(x,0,10) for x in big_shape] 
    #combine the two big_shapes so they can be plotted at once 
    big_shape.extend(new_big_shape) 

    return big_shape 


plt.axes() 

#Below is the information for four unit_squares that will make up a big_shape 
big_shape_1_info = [ [[0,1],'green'], [[0,2], 'green'], [[1,2],'green'], [[1,1],'pink'] ] 
#Take that information and create a list of unit_squares, i.e. a big_shape. 
big_shape_1 = [make_unit_square(x) for x in big_shape_1_info] 
''' 
Here we make an even larger big_shape by making a transposed copy of big_shape_1 and saving both the original 
big_shape and its copy into one new big_shape. However, due to the bug, the unit_squares of big_shape_1 are 
erroneously changed in this step, so what we get is not the original big_shape and a transposed copy, but rather 
two transposed copies and no original. 
''' 
big_shape_2 = make_copies(big_shape_1) 
''' 
Next, we plot the new big_shape. This plotting is done by plotting each individual unit_square that makes up the big_shape. 
''' 
for unit_square in big_shape_2: 
    pol = plt.Polygon(unit_square['points'],color=unit_square['color']) 
    plt.gca().add_patch(pol) 
    print(unit_square) 



plt.axis('scaled') 
plt.show() 
+0

'new_unit_square = unit_square'将只复制引用,不复制对象。尝试['copy()'](https://docs.python.org/2/library/copy.html)函数。 – Selcuk

回答

2

当你做什么看起来是一项任务,

d = {1:[1,2,3]} 
D = d 

您只需将的新名称添加到字典对象 - 同样的推理适用于列表和其他可变对象 - 基础是对象,现在您可以使用不同的名称来引用同一对象。

无论哪个名字,你用它来修改一个对象,所有这些名字引用同一个对象

d[2] = 3 
D[3] = 4 
print d, D # --> {1:[1,2,3], 2:3, 3:4}, {1:[1,2,3], 2:3, 3:4} 

在您的使用情况下,你想字典的副本...

根据在字典的内容中,可以使用copy模块中字典的.copy()方法或copy.deepcopy(...)函数。

的方法给你一个所谓的复制,因此复制是一个字典,但如果项目是可变,当你在原来的字典更改的项目,也该项目被修改

d = {1:[1,2,3]} 
D = d.copy() 
D[2] = '2' 
print d # --> {1:[1,2,3]} --- no new element in original 
D[1][0] = 0 
print d # --> {1:[0,2,3]} --- the original mutable content is modifed 

如果字典中的所有项目都不可变(例如,字符串,数字,元组),那么.copy()就可以。

在另一方面,如果你有可变的项目(例如,列表,字典等),你想独立副本,你想copy.deepcopy()

from copy import deepcopy 
d = {1:[1,2,3]} 
D = deepcopy(d) 
D[1][0]=0 
print d # --> {1:[1,2,3]} 

附: D = d.copy()等同于创建一个新的字典,D = dict(d):在这种情况下,您拥有的是浅拷贝。

1

Python是其中分配经过参考暗示的语言。所以,当你这样做:

new_unit_square = unit_square 

你只是建立一个别名unit_square

尝试以下操作:

import copy 
new_unit_square = copy.deepcopy(unit_square) 

点击此处了解详情:https://docs.python.org/2/library/copy.html

+0

“dict”类没有'deepcopy()'方法。 – Selcuk

+1

对不起,你是对的。编辑 –

相关问题