Анализ ошибки в коде для генерации фракталов с помощью системы Лиденмайера

    Я разрабатывал класс для рисования фрактальных фигур, используя L-систему (систему Лиденмайера). В реализации возникла ошибка выполнения, требующая детального разбора.

    Исходный код

    Приведу ключевые фрагменты моего класса instinctTurtle, унаследованного от turtle.Turtle:

    class instinctTurtle(turtle.Turtle):
        axiom = ''
        turtleX = 0
        turtleY = 0
        turtleRotate = 0.0
        teta = 0
        lenght = 0
        
        def __init__(self, shape="classic", undobuffersize=1000, visible=False):
            super().__init__(shape, undobuffersize, visible)
        
        def setDrawingParameters(self, teta=60, lenght=10, axiom='F++F++F', 
                                 newF='F-F++F-F', newB='B', newK='K'):
            self.teta = teta
            self.lenght = lenght
            self.axiom = axiom
            self.newF = newF
            self.newB = newB
            self.newK = newK
        
        def createInstinct(self, deep=1):
            self.instinct = ''
            for i in range(deep):
                for j in range(len(self.axiom)):
                    instinct = ''
                    match self.axiom[j]:
                        case 'F':
                            instinct += self.newF
                        case 'B':
                            instinct += self.newB
                        case 'K':
                            instinct += self.newK
                        case _:
                            instinct += self.axiom[j]
                    self.axiom = instinct
        
        def runInstinct(self):
            for i in range(len(self.axiom)):
                cmd = self.axiom[i]
                match cmd:
                    case 'F':
                        self.forward(self.lenght)
                    case 'B':
                        self.up()
                        self.forward(self.lenght)
                        self.down()
                    case '+':
                        self.right(self.teta)
                    case '-':
                        self.left(self.teta)
                    case '[':
                        self.turtleX = self.xcor()
                        self.turtleY = self.ycor()
                        self.turtleRotate = self.heading()
                    case ']':
                        self.setx(self.turtleX)
                        self.sety(self.turtleY)
                        self.setheading(self.turtleRotate)

    Проблема при выполнении

    При запуске следующего кода:

    N = instinctTurtle()
    N.setDrawingParameters()
    N.createInstinct(3)
    N.runInstinct()

    Возникает ошибка:

    Traceback (most recent call last):
      File "E:\Python\Библиотеки\turtleGeometry\src\turtleGeometry\main.py", line 142, in 
        N.createInstinct(3)
      File "E:\Python\Библиотеки\turtleGeometry\src\turtleGeometry\main.py", line 108, in createInstinct
        match self.axiom[j]:
    IndexError: string index out of range

    Диагностика проблемы

    Основная ошибка находится в методе createInstinct. Рассмотрим логику работы этого метода:

    • Внешний цикл for i in range(deep) должен выполнить заданное количество итераций (в данном случае 3)
    • Внутренний цикл for j in range(len(self.axiom)) проходит по символам аксиомы
    • Проблема возникает из-за того, что внутри внутреннего цикла происходит перезапись self.axiom = instinct

    Это приводит к следующему:

    1. На первой итерации внешнего цикла (i=0) длина аксиомы равна 7 ('F++F++F')
    2. Внутренний цикл начинает обрабатывать символы, но после обработки первого символа 'F' аксиома заменяется на строку 'F-F++F-F'
    3. Когда внутренний цикл пытается обратиться к self.axiom[1], строка уже имеет другую длину и содержимое
    4. Если новая строка короче исходной, возникает IndexError

    Дополнительные наблюдения

    Мои эксперименты подтверждают эту гипотезу:

    • При замене self.axiom[j] на self.axiom[0] программа рисует одну итерацию, затем зависает
    • При использовании индекса 1 возникает та же ошибка IndexError
    • Ошибка связана не с работой range, а с изменением строки во время итерации по ней

    Рекомендации по исправлению

    Для корректной работы метода createInstinct необходимо:

    1. Создавать новую строку для каждой итерации внешнего цикла
    2. Не изменять исходную строку во время итерации по ней
    3. Использовать временную переменную для накопления результата

    Примечание: Перехожу на Python с JavaScript, поэтому в коде присутствует camelCase. Прошу отнестись с пониманием к стилистическим особенностям.