Возможно ли сократить эту функцию?

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

def info():
    lvl = wynnpars.lvl
    precent = wynnpars.precent
    warcount = wynnpars.warcount
    totalm = wynnpars.totalm
    owner = wynnpars.owner
    o_owner = wynnpars.o_owner
    chief = wynnpars.chief
    o_chief = wynnpars.o_chief
    strategist = wynnpars.strategist
    o_strategist = wynnpars.o_strategist
    recruits = wynnpars.recruirt
    o_recruits = wynnpars.o_recruit
    return render_template('info.html',
                            lvl = lvl,
                            precent = precent, 
                            warcount = warcount, 
                            owner = owner, 
                            recruits = recruits, 
                            totalm = totalm,
                            chief = chief, 
                            strategist = strategist, 
                            strat = range(len(strategist)), 
                            rec = range(len(recruits)), 
                            o_owner = o_owner,
                            o_chief = o_chief,
                            o_str = o_strategist,
                            o_rec = o_recruits
                          )

Ответы (1 шт):

Автор решения: artur1214

Не совсем понятно, что за объект wynnparse (Какой у него тип)

Но скорее всего вам поможет вот такой способ:

def info():
    return render_template('info.html', **vars(wynnpars))  # Или wynnpars.__dict__

Что здесь происходит?

В большинстве случаев вы можете получить доступ ко всем элементам объекта python, используя obj.__dict__ или vars(obj)

(За исключением следущих случаев):

  • Slot based class (Класс, переопределяющий __slots__ (см. Ориг. Документацию или Неплохой ответ на stackoverlflow)
  • Dataclass (классы с декоратором @dataclass не имеют __dict__)
  • Классов из друг их языков (например C-based классы, написанные на чистом С)
  • Именованные картежи (объекты collections.namedtuple так же не имеют __dict__)

__dict__ - по сути обычный питоновский словарь (dict), который хранит все данные объекта в виде пар ключ значение (как и все словари) например:

class Example:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
        self.text = 'Hello world'

object_example = Example(1, 3, 5)

print(vars(object_example))

print(object_example.__dict__)

Оба print'a выведут одинаковый результат, словарь, с переменными и их значениями:

Вывод

И так, vars(obj) (так же как и obj.__dict__) Позволяют из объекта получить словарь со списокм его переменных.

Далее все что нам остается это полученный словарь значений передать в функцию. Используя **dict синтаксис мы можем передать словарь в функцию, как если бы каждый из ключей мы подставляли напрямую (См. операторы распаковки Python:

class Example:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
        self.text = 'Hello world'


def some_func(c, b, a, text):
    print(f'получены значения: \n{a = }\n{b = }\n{c = }\n{text = }')


obj = Example(5, 6, 7)

print('VARS Результат: \n')
some_func(**vars(obj))

print('\nОбычный результат: \n')
some_func(
    a=obj.a,
    b=obj.b,
    c=obj.c,
    text=obj.text
)

Код выше показывает 2 способа предачи значений объекта в функцию, как у вас, и через vars() и оператор **

Рузультаты будут идентичны:

Еще вывод

Таким образом, вы можете передавать каждое из значений через **vars, и сократить код.

ВАЖНО! Обратите внимание, ключи, под которыми передаются переменные, будут соответствовать названию переменных в объекте. Таким образом, использование

lvl = wynnpars.lvl

precent = wynnpars.precent

warcount = wynnpars.warcount

owner = wynnpars.owner

recruits = wynnpars.recruits

Не вызовет, проблем, но в местах, где название ключа в шаблоне не соотвтствует переменной в wynnpars, например:

o_str = wynnpars.o_strategist

o_rec = wynnpars.o_recruit

Приведет к тому, что при использовании **wynnpars.__dict__ в вашем шаблоне переменной с названием o_rec не будет, но будет o_recruit. В таком случае вам нужно будет изменить шаблон, либо скомбинировать 2 варианта.

Комбинации:

В вашем примере часть названий переменных в шаблоне, соответствуют переменным в wynnpars, а часть - нет. К тому же, часть из них, вообще вычисляет по ходу, и не присутствует в оригинальном wynnpars, например

strat = range(len(strategist))

В таком случае, такие переменные вы можете передавать совместно, примерно так:

def info():
    return render_template('info.html',
                           **vars(wynnpars),
                           strat=range(len(wynnpars.strategist)),
                           rec=range(len(wynnpars.recruirt)),
                           o_str=wynnpars.o_strategist,
                           o_rec=wynnpars.o_recruit
                           )

Здесь те переменные, названия которых совпадают с полями wynnpars, опускаются, потому что они передадутся автоматически, вместе с **vars(wynnpars).

Поля, которые вычисляются по ходу, передаются следом, как обычно, и вычисляются из других полей переменной wynnpars.

Ну и в конце передаются те переменные, названия которых не совпадают с названиями переменных в оригинальном объекте wynnpars. Благодаря этому, вам не придется изменять в шаблоне все использования переменной o_rec на o_recruit

P.S. Еще одно отступление

vars(obj) - по сути просто один из способов получить значение в obj.__dict__.

Большинство источников предлагает vars(obj) как более предпочтительный для использования вариант, считая его более читаемым.

Лично для меня obj.__dict__ всегда был понятнее, поэтому предлагаю вам самостоятельно выбрать, какой из вариантов ВАМ нравится больше.

→ Ссылка