0

So, I've been trying to make a Dragon Curve with Python, Pygame, and what I've done is have a main file for running it and have a curve.py file where I put the Curve class. The Curve class is pretty simple (and incomplete) at the moment, but here's how it works: there's a positions value which should hold the line's positions (I'm basically first drawing a line, then duplicating it, and rotate it 90 degrees, then instead of a line, this time I'm drawing the object I've drawn (2 lines with a 90 degrees angle between them) with a 90 degrees difference in angle to the previous one), then I have a current_shape list which holds the start and end points of the current shape lines, then there is next_shape which is for the duplicate object (which then rotates 90 degrees and then merges with the initial object). So this is my Curve class right now:

class Curve:
    def __init__(self, shape_start, multiplier, counter): # counter is for making only a number of curves
        self.multiplier = multiplier
        self.positions = [shape_start]
        self.current_shape = [[shape_start, [self.positions[0][0] + self.multiplier, self.positions[0][1]]]]
        self.counter = counter
        self.next_shape = [[shape_start, [self.positions[0][0] + self.multiplier, self.positions[0][1] + self.multiplier]]]

    def copy_object(self):
        self.next_shape = self.current_shape.copy()

    def rotate_next(self, degrees):
        for id, line in enumerate(self.next_shape):
            line[1][0] = self.positions[id][0] + int(cos(degrees/180*pi)*self.multiplier)
            line[1][1] = self.positions[id][1] + int(sin(degrees/180*pi)*self.multiplier)

    def merge(self):
        self.current_shape = self.current_shape.copy() + self.next_shape.copy()

    def draw(self, display):
        for line in self.current_shape:
            pygame.draw.line(display, (100, 100, 255), (line[0][0], line[0][1]), (line[1][0], line[1][1]), 2)
            self.counter -= 1

(note: counter is for the iteration of the curve, I can't let it make curves forever you know!)

my problem right now is that when I rotate_next(90), it rotates both of them. here's a part of main.py which holds the order of the functions:

        dragoncurve.copy_object()
        dragoncurve.rotate_next(90)
        dragoncurve.merge()
        dragoncurve.draw(screen)

so yea, first I copy current_shape to next_shape, then I rotate next_shape 90 degrees, then I merge the 2 lists, then I draw current_shape.

What is wrong with this?

RaderH2O
  • 3
  • 1
  • 1
  • 5
  • Isn’t it just that you’re copying the outer list and then mutating the contents of the shared(!) inner lists? – Davis Herring Jul 08 '22 at 20:18
  • I mean, I am using `list.copy()`, which I assume should not make the other list be able to change the contents of the initial list... right? – RaderH2O Jul 08 '22 at 20:34
  • Copying a list produces a *new* list with the *same* elements, not new elements with the same values. – Davis Herring Jul 08 '22 at 20:38

1 Answers1

0

list2=list1.copy() makes a shallow copy. That means that list2 is a new object and not a reference to list1, but all the elements in list1 are still references in list2. If an element of list1 is a mutable object, when it is changed, the corresponding element in list2 is also changed. You should use copy.deepcopy(). But first you have to import copy.

def copy_object(self):
    import copy
    self.next_shape = copy.deepcopy(self.current_shape)
  • ahhhhhhh I understand now! So basically a list inside a list doesn't get affected with the `.copy()` *shallow* copy, and it is still mutable, but when you do a deep copy, all of the items inside the list are immutable right – RaderH2O Jul 09 '22 at 06:07
  • No. You don’t change the mutability of the object. When performing an assignment, you either bind a variable to an object or to a copy of it (using copy() and deepcopy()). – Иван Балван Jul 09 '22 at 09:08
  • You don't have to use `copy.copy()` or `copy.deepcopy()` on immutable objects. These are functions from the `copy` module. Mutable objects of built-in classes `List`, `dict` and `set` has a similar method to the function `copy.copy`, called 'copy'. Immutable objects of built-in classes do not have this method. They don't need it. (A class method is a function defined in this class) – Иван Балван Jul 09 '22 at 10:01