为什么我的函数在函数范围之外更改其参数?

时间:2016-05-17 14:14:21

标签: python matplotlib

我的程序使用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.

问题似乎来自transpose()函数。我期望函数接受一个单位正方形的输入并输出转换到新位置的该单位正方形的一个副本,而不影响原始单位正方形。但是,转置函数似乎正在影响输入单位方格,使得它最终在转置点中同时绘制原始和转置。

你能帮我弄清楚为什么transpose()函数没有按预期运行吗?

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()

2 个答案:

答案 0 :(得分: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.deepcopy(...)模块中的copy函数。

该方法为您提供了所谓的副本,因此副本是字典,但如果项目是可变,则何时你修改一个项目也修改了原始字典中的项目

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]}

P.S。 D = d.copy()相当于创建一个新词典D = dict(d):在这种情况下,你所拥有的是一个浅层副本。

答案 1 :(得分: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

相关问题