Почему этот код L-системы не возвращает строку?

Я пытаюсь написать программу, которая берет строку и заменяет определенные символы другими строками. (A->AB) и (B->A) в этом случае. Когда я запускаю его, я ожидаю, что будет возвращена окончательная строка, но вместо этого ничего не возвращается.

def createSystem(seed,depth):

    startString = seed
    endString = ""

    for i in range(depth): 
        endString = processString(startString)
        startString = endString
    return endString   


def processString(oldstr):
    newstr = ""
    for char in oldstr:
        newstr=newstr+applyrules(oldstr)

    return(newstr)

def applyrules(oldstr):
    output = ""

    for char in oldstr:
        if char= = "A":
            output.join("AB")
        elif char= = "B":
            output.join("A")

    return(output)


print(createSystem("AB",1))

В этом примере я ожидал бы, что семя «AB» создаст строку «ABA», однако на консоль ничего не возвращается. Почему это? Заранее спасибо! - Эли

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

@Andreas Хотя для новых программистов важно изучить основные методы отладки, я не думаю, что это поможет здесь; то, как написан код, наводит меня на некоторые неправильные представления о том, как на самом деле работают различные вещи.

Karl Knechtel 13.07.2019 14:39

Кстати, код делает создает строку - просто пустую.

Karl Knechtel 13.07.2019 14:45
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
29
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, вы ожидаете, например,

output = ""
output.join("AB")

означает: «output — пустая строка; теперь заставьте output стать результатом добавления 'AB' в конец существующего output».

Это не.

Это означает: «output — пустая строка; теперь создайте новую строку, поместив существующую output между каждым символом 'AB', и выбросьте эту новую строку (не давайте ей имени)».

В Python строки — это неизменный — никакие действия с ними не могут изменить их содержимое на месте, как со списком. Вы должны использовать операцию, которая создает новую строку, и переназначить результат. Кроме того, метод join используется для получения целых строк последовательность и их объединения, например:

' '.join(['a', 'b', 'c']) # produces 'a b c'

Код не вызывает ошибку, потому что строка Python также является допустимой последовательностью строк (каждая из которых состоит из одного символа). Это особое поведение строк, не разделяемое другими последовательностями.

Чтобы использовать этот метод здесь, вам нужно создать последовательность фрагментов 'AB' и 'A' и просто вызвать ''.join (т. е. мы поместим пустую строку между каждым фрагментом), чтобы получить результат напрямую. Мы можем сделать это с помощью выражение генератора. Это выглядит так:

def process_string(oldstr):
    return ''.join(
        'AB' if char == 'A' else 'A'
        for char in oldstr
    )

(Обратите внимание на соглашение об именах для функции — см. ПКП 8 для стандартных соглашений о стиле в Python)

Это действительно все, что вам нужно. Или вы можете применить логику +=, которую вы имели в виду в исходном коде, для построения строки по частям (это менее эффективен):

def process_string(oldstr):
    newstr = ''
    for char in oldstr:
        newstr += 'AB' if char == 'A' else 'A'
    return newstr # parentheses are meaningless here.

Или вы можете использовать встроенную поддержку такого рода перевода строк, уже предоставленную классом строк (но это более неудобно, чем должно быть):

def process_string(oldstr):
    return oldstr.translate(str.maketrans({'A': 'AB', 'B': 'A'}))

Здесь str.maketrans вызывает метод класса, принадлежащий классу строк (с именем str и доступный автоматически как глобальный при запуске). Вы можете прочитать об этих методах в документации по языку: str.translate; str.maketrans.

Похоже, вы запутались и пытались сделать и то, и другое. Спасибо за попытку поместить логику правила преобразования в отдельную функцию (applyrules), но эта функция должна возвращать только фрагмент, соответствующий одному входному символу. (В конце концов, вы уже настроили перебор символов и спроектировали applyrules так, чтобы он принимал по одному символу за раз.) Работа, которую он выполняет, достаточно проста, поэтому — по крайней мере, на данный момент — отдельная функция на самом деле не нужна. необходимо (если это не поможет вам понять код).

В приведенных выше примерах я использовал тернарный условный оператор для представления логики выбора фрагмента замены для каждого входного символа. Это необходимо для подхода с выражением генератора, потому что вы пишете один выражение и вам некуда поместить блок if:/else:.

В качестве примечания: совершенно безопасно просто продолжать повторно использовать одно и то же имя для повторного назначения результата каждого шага в createSystem вместо того, чтобы перетасовывать вещи между двумя отдельными именами. Вы даже можете просто использовать имя входного параметра (seed).

Karl Knechtel 13.07.2019 14:42

Другие вопросы по теме