Производительность назначения нескольких возвращаемых значений из вызова функции

Мне интересно, есть ли способ присвоить выходные данные функции переменным, при этом нужно только запустить функцию один раз. Например, скажем, у меня есть такая функция:

def my_func(x):
    return x+1, x**2, x**3

И затем я хочу сохранить каждый вывод как переменную, поэтому обычно я буду кодировать это потом:

var1 = my_func(2)[0]
var2 = my_func(2)[1]
var3 = my_func(2)[2]

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

2 ответа

Решение

Две возможности:

назначить возвращаемое значение функции (которая является tuple) к переменной и доступ к ее элементам:

var = my_func(2)
var1 = var[0]
var2 = var[1]
var3 = var[2]

или используйте распаковку:

var1, var2, var3 = my_func(2)

Re: Какой метод работает быстрее в большинстве случаев?

Давайте сравним разбирать (я подсчитал с > различия):

dis.dis('t=my_func(2);d=t[0]+t[1]+t[2]')

  1           0 LOAD_NAME                0 (my_func)
              2 LOAD_CONST               0 (2)
              4 CALL_FUNCTION            1
           >  6 STORE_NAME               1 (t)
              8 LOAD_NAME                1 (t)
           > 10 LOAD_CONST               1 (0)
           > 12 BINARY_SUBSCR
             14 LOAD_NAME                1 (t)
           > 16 LOAD_CONST               2 (1)
           > 18 BINARY_SUBSCR
             20 BINARY_ADD
             22 LOAD_NAME                1 (t)
           > 24 LOAD_CONST               0 (2)
           > 26 BINARY_SUBSCR
             28 BINARY_ADD
             30 STORE_NAME               2 (d)
             32 LOAD_CONST               3 (None)
             34 RETURN_VALUE

dis.dis('a,b,c=my_func(2);d=a+b+c')

  1           0 LOAD_NAME                0 (my_func)
              2 LOAD_CONST               0 (2)
              4 CALL_FUNCTION            1
          >   6 UNPACK_SEQUENCE          3
          >   8 STORE_NAME               1 (a)
          >  10 STORE_NAME               2 (b)
          >  12 STORE_NAME               3 (c)
             14 LOAD_NAME                1 (a)
             16 LOAD_NAME                2 (b)
             18 BINARY_ADD
             20 LOAD_NAME                3 (c)
             22 BINARY_ADD
             24 STORE_NAME               4 (d)
             26 LOAD_CONST               1 (None)
             28 RETURN_VALUE

Итак, первый подход требует еще две инструкции каждый раз, когда используется переменная (LOAD_CONST, BINARY_SUBSCR), тогда как второй подход требует еще одну инструкцию при создании переменной.

Разница практически бессмысленная.

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

def my_func(x):
    return x+1, x**2, x**3

var1, var2, var3 = my_func(2)

Эта функция описана в документации: кортежи и последовательности

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