Function unwantedly alters variables
Question: I am wanting to use the baseTriangle and baseSquare variables in my for loops
in the rotateshape(), but when they are put in, the funnction seems to alter
them, meaning that they get bigger with every loop. not sure why it does this,
please help!!!

    
    
        #! /usr/bin/env python
    
        import Image, ImageDraw
        import math
    
        # functions
    
        def rotateShape(shapeXCoordinates, shapeYCoordinates, baseXCoordinates, baseYCoordinates):
    
            # Written by: some guy who had to do this once and thought it better to share rather than let other people suffer through the monotony
    
            # This function below takes a shape and rotates, scales and translates it so that the first two coordinates are equal to the baseCoordinates
    
            # Make sure that the distance between the first two shape coordinates is 1 and that they lie on the x-axis
    
    
    
            # Find the dx, dy and the length of the baseCoordinates pair
            #print 'Base coordinates: ' + str(zip(baseXCoordinates, baseYCoordinates))
            dx = baseXCoordinates[1] - baseXCoordinates[0]
            #print 'dx: ' + str(dx)
            dy = baseYCoordinates[1] - baseYCoordinates[0]
            #print 'dy: ' + str(dy)
            magnitude = math.sqrt(dx**2+dy**2)
            #print 'magnitude: ' + str(magnitude)
    
            #print 'Start: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
    
            # Rotate the matrix
            a = dx/magnitude
            b = -dy/magnitude
            c = dy/magnitude
            d = dx/magnitude
    
            for i in range(0,len(shapeXCoordinates)):
    
                # Find the new x value
                newX = a*shapeXCoordinates[i]+b*shapeYCoordinates[i]
    
                # Find the new y value
                newY = c*shapeXCoordinates[i]+d*shapeYCoordinates[i]
    
                # Replace the old with the new
                shapeXCoordinates[i] = newX
                shapeYCoordinates[i] = newY
    
            #print 'After rotate: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
    
            # Scale the matrix
            for i in range(0,len(shapeXCoordinates)):
    
                shapeXCoordinates[i] = shapeXCoordinates[i]*magnitude
                shapeYCoordinates[i] = shapeYCoordinates[i]*magnitude
    
            #print 'After scale: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
    
            # Translate the matrix
            for i in range(0,len(shapeXCoordinates)):
    
                shapeXCoordinates[i] = shapeXCoordinates[i]+baseXCoordinates[0]
                shapeYCoordinates[i] = shapeYCoordinates[i]+baseYCoordinates[0]
    
            #print 'After translate: ' + str(zip(shapeXCoordinates, shapeYCoordinates))
            return (shapeXCoordinates, shapeYCoordinates)
    
        # create a bitmap
    
        img = Image.new('RGB', (3840, 2160))
        draw = ImageDraw.Draw(img)
    
        # setting up the varibales
    
        # insert angle
    
        angle = 30
        angle_2 = 90 - angle
        a = math.sin(angle_2) * 1
    
        # working out the Y of the triangle
    
        y = math.sin(angle) * a
    
        # working out the X of Y
    
        x = math.tan(angle)/y
    
        baseTriangle_X = [0, 1, x]
        baseTriangle_Y = [0, 0, y]
    
        baseSquare_X = [0, 1, 1, 0]
        baseSquare_Y = [0, 0, 1, 1]
    
        startPosition_X = [1800, 2200] # flipped numbers as bitmap counts from the top left so that tree is created downwards
        startPosition_Y = [0, 0]
    
        # set number of iterations
    
        numberOfIterations = 10
    
        # set colour
    
        redStart = 255
        greenStart = 253
        blueStart = 208
    
        redEnd = 228
        greenEnd = 82
        blueEnd = 0
    
        # colour change
    
        redChange =(redEnd - redStart)/numberOfIterations
        greenChange =(greenEnd - greenStart)/numberOfIterations
        blueChange =(blueEnd - blueStart)/numberOfIterations
    
        # set up the list of squares to make (fill with the start position)
    
        squaresToMake_X = []
        squaresToMake_Y = []
    
        squaresToMake_X.extend(startPosition_X)
        squaresToMake_Y.extend(startPosition_Y)
    
        # set up the list of triangles
    
        trianglesToMake_X = []
        trianglesToMake_Y = []
    
        # creating the tree
    
        print '//////////////////////////////'
        print '//     //     //     //     //'
        print '//// //// ////// ////// //////'
        print '//// //// //////     //     //'
        print '//// //// ////// ////// //////'
        print '//// //// //////     //     //'
        print '//////////////////////////////'
    
        # background colour
    
        draw.rectangle((0,0,3839,2759), fill=(220, 255, 250))
    
        for i in xrange(0, numberOfIterations):
    
            redCurrent =  redStart + redChange  * i
            greenCurrent =  greenStart + greenChange  * i
            blueCurrent =  blueStart + blueChange  * i
    
            # making squares
    
            for j in xrange(0, len(squaresToMake_X)/2):
    
                print 'Iteration ' + str(i) + ' of ' + str(numberOfIterations) + '. Square ' + str(j) + ' of ' +  str(len(squaresToMake_X)/2)
                k = j * 2
    
                newVertices_X, newVertices_Y = rotateShape([0, 1, 1, 0], [0, 0, 1, 1], squaresToMake_X[k:k+2], squaresToMake_Y[k:k+2])
    
                # merge x and y
                combinedVertices = zip(newVertices_X, newVertices_Y) 
    
                # draw 
                #print 'Drawing square:'
                #print combinedVertices
                draw.polygon(combinedVertices, fill = (redCurrent, greenCurrent, blueCurrent))
    
                trianglesToMake_X.extend([newVertices_X[3], newVertices_X[2]])
                trianglesToMake_Y.extend([newVertices_Y[3], newVertices_Y[2]])
    
                #print 'Triangles to make:'
                #print zip(trianglesToMake_X, trianglesToMake_Y)
    
            squaresToMake_X = []
            squaresToMake_Y = []
    
            # making triangles
    
            for j in xrange(0, len(trianglesToMake_X)/2):
    
                print 'Iteration ' + str(i) + ' of ' + str(numberOfIterations) + '. Triangle ' + str(j) + ' of ' +  str(len(trianglesToMake_X)/2)
                k = j * 2
                newVertices_X, newVertices_Y = rotateShape([0, 1, 0.5], [0, 0, 0.5], trianglesToMake_X[k:k+2], trianglesToMake_Y[k:k+2])
    
                # merge x and y
                combinedVertices = zip(newVertices_X, newVertices_Y)
    
                # draw
                #print 'Drawing triangle:'
                #print combinedVertices
                draw.polygon(combinedVertices, fill = (redCurrent, greenCurrent, blueCurrent))
    
                squaresToMake_X.extend([newVertices_X[0], newVertices_X[2], newVertices_X[2], newVertices_X[1]])
                squaresToMake_Y.extend([newVertices_Y[0], newVertices_Y[2], newVertices_Y[2], newVertices_Y[1]])
    
                #print 'Squares to make:'
                #print zip(squaresToMake_X, squaresToMake_Y)
    
            trianglesToMake_X = []
            trianglesToMake_Y = []
    
    
            print '----------'
    
        img2=img.rotate(180)
        img2.show()
    


Answer: `list` objects are mutable, so when you pass them into a function, a reference
to the original list is passed, rather than a copy. Therefore when you
_modify_ the list, such as with `shapeXCoordinates[i] = newX`, you're
modifying the _original_ list at the same time.

If you only want modifications to stay local to the function, without changing
the original, you need to make a copy of the list first:

    
    
    shapeX = shapeXCoordinates[:]
    

Then reference `shapeX` everywhere in the function, rather than
`shapeXCoordinates`.

Obviously name the variables however makes sense to you.

