Python - Как объединить строки в последовательный путь?

Не могли бы вы рассказать мне, есть ли более элегантное решение для моего кода, что мне нужно?

Моя маленькая программа принимает текстовый ввод из семи полей ввода (точное число может быть указанный пользователем). Входные строки затем объединяются с вкрапленным фиксированным текстовые элементы. Создается один вывод в виде строки.

Программа работает отлично. Тем не менее, мое программирование поражает меня как очень неэлегантного и непифонного. Могли бы вы помочь мне улучшить, чтобы способствовать обучению?

Две точки:

1) Мне нравится суммировать длину строки из всех семи текстовых входов. Я просто добавил их, который не является элегантным. Как я мог сделать это лучше?

string_length = len(str(E1.get())) + len(str(E2.get())) + len(str(E3.get())) +   len(str(E4.get())) + len(str(E5.get())) + len(str(E6.get())) + len(str(E7.get()))

2) В зависимости от количества полей ввода, которые могут быть заданы пользователем с использованием шкалы Tkinter S, поля ввода (En) включены или отключены для ввода ввода.

Строки str (En.get()), полученные из этого поля ввода, затем объединяются с помощью фиксированные строковые элементы partM между ними, чтобы создать строку m. (Вся строка окружена partL и partR с каждой стороны.) Я сделал это, выполнив запрос переменной масштаб S (количество полей ввода) с помощью метода get(). Затем программа решает, как продолжить, если /elif?

Чем выше установлен масштаб, тем больше добавляются текстовые элементы. Тем не менее это очень похожее задание, которое меня поражает, поскольку может быть более прямое решение.

Это создает длинные строки кода и не очень поддается расширению программы для получения дополнительных полей ввода. Как я мог сделать это лучше?

выдержка кода:

if S.get() == 1:
    if string_length == 22*S.get():        
        m = partL + str(E1.get()) + partR
        do_something()
    else:
        warning()

elif S.get() == 2:
    if string_length == 22*S.get():            
        m = partL + str(E1.get()) + partM + str(E2.get()) + partR
        do_something()
    else:
        warning()

elif S.get() == 3:
    if string_length == 22*S.get():
        m = partL + str(E1.get()) + partM + str(E2.get()) + partM + str(E3.get()) + partR
        do_something()
    else:
        warning()

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

Ответ 1

Если ваши поля от E1 до E7 и каждый из них имеет метод get, это должно дать вам общую длину:

fields = [E1, E2, E3, E4, E5, E6, E7]
total_length = sum(len(str(f.get())) for f in fields)

Если вам просто нужны собранные значения, этого достаточно:

fields = [E1, E2, E3, E4, E5, E6, E7]
values = [f.get() for f in fields]

Ответ 2

Я попробую ответить на вторую часть вопроса, так как @g.d.d.c уже имеет очень хороший ответ на первую часть.

Чтобы избежать повторения кода, вы должны посмотреть общие разделы среди вашего существующего кода.

if string_length == 22*S.get():
    ...
else:
    warning()

появляется во всех трех случаях. Поэтому вы можете выделить его как:

if string_length != 22*S.get():
    warning()
else:     
    if S.get() == 1:
        ...
    elif S.get() == 2:
        ...
    elif S.get() == 3:
        ...
    do_something()

если вы планируете поддерживать больше случаев, вы можете расширить с помощью карты функций

functions = {1 : one,
                2 : two,
                3 : three
}

def one():
    m = partL + str(E1.get()) + partR

def two():
    m = partL + str(E1.get()) + partM + str(E2.get()) + partR

def three():
    m = partL + str(E1.get()) + partM + str(E2.get()) + partM + str(E3.get())

и вы вызываете с помощью:

functions[S.get()]()

Ответ 3

Проверка if string_length == 22*S.get() выполняется независимо от значения S.get(), и если она терпит неудачу, вы всегда вызываете предупреждение. Чтобы упростить код и уменьшить дублирование кода, вы можете переместить эту проверку за пределы логики, которая переключается на основе значения S.get():

if string_length != 22*S.get():
    warning()
else:
    if S.get() == 1:
        ...
    elif S.get() == 2:
        ...
    ...

Если вы создаете список полей вместо 7 нумерованных переменных, легко использовать нарезку и индексирование для выбора полей, которые вы хотите масштабируемым образом, не требуя отдельных предложений для каждого номера. Кроме того, метод строк join позволяет вам объединить несколько строк с указанным разделителем:

if string_length != 22*S.get():
    warning()
else:
    middle = partM.join(str(field.get()) for field in fields[:S.get()])
    m = partL + middle + partR
    do_something()

Разбейте partM.join(str(field.get()) for field in fields[:S.get()]):

fields должен быть списком полей, которые вы сделали вместо использования 7 переменных.

fields[:S.get()] обозначает нотацию нарезки. Он составляет список первых S.get() элементов fields. (Если fields не хватает элементов, срез возвращает копию всего списка.)

str(field.get()) for field in fields[:S.get()] является выражением генератора. Он создает итератор, который пересекает fields[:S.get()] и вызывает метод get() для каждого поля в списке. Это приводит к итератору по строкам из первых полей S.get(). (Генерирующие выражения должны всегда отображаться в круглых скобках.Если выражение генератора является единственным аргументом функции, то в эту скобку входят круглые скобки вызова функции. В противном случае вы должны вставлять в нее круглые скобки.)

partM.join(str(field.get()) for field in fields[:S.get()]) берет все строки из этого итератора и связывает их вместе, разделяя их на partM между каждой парой строк.

Ответ 4

Ну, способ присоединиться к строкам, чтобы использовать метод .join(insert something here). Это в основном строковый эквивалент функции .append(Вставьте что-то здесь).