Pythonic способ эффективно обрабатывать переменное число возвращаемых аргументов
Итак, у меня есть функция, которая может работать тихо или многословно. В тихом режиме он производит выход. В подробном режиме он также сохраняет промежуточные вычисления в списке, хотя это делает дополнительные вычисления сами по себе.
Прежде чем спросить, да, это идентифицированное узкое место для оптимизации, и подробный вывод редко необходим, так что это нормально.
Итак, вопрос в том, какой самый пифонический способ эффективно обрабатывать функцию, которая может или не может вернуть второе значение? Я подозреваю, что питонический путь будет называться кортежами или выходом словаря, например.
def f(x,verbose=False):
result = 0
verbosity = []
for _ in x:
foo = # something quick to calculate
result += foo
if verbose:
verbosity += # something slow to calculate based on foo
return {"result":result, "verbosity":verbosity}
Но для этого требуется построить dict, если это не требуется.
Некоторые альтернативы:
# "verbose" changes syntax of return value, yuck!
return result if verbose else (result,verbosity)
или используя изменяемый аргумент
def f(x,verbosity=None):
if verbosity:
assert verbosity==[[]]
result = 0
for _ in x:
foo = # something quick to calculate
result += foo
if verbosity:
# hard coded value, yuck
verbosity[0] += # something slow to calculate based on foo
return result
# for verbose results call as
verbosity = [[]]
f(x,verbosity)
Любые лучшие идеи?
Ответы
Ответ 1
Не возвращайте verbosity
. Сделайте это необязательным аргументом функции, переданным вызывающим, мутированным в функции, если не пустым.
Непифонной частью некоторых ответов является необходимость проверки структуры возвращаемого значения. Передача измененных аргументов для дополнительной обработки позволяет избежать этого уродства.
Ответ 2
Мне нравится первый вариант, но вместо передачи параметра verbose
в вызове функции верните кортеж быстрого результата и ленивую оценку:
import time
def getResult(x):
quickResult = x * 2
def verboseResult():
time.sleep(5)
return quickResult * 2
return (quickResult, verboseResult)
# Returns immediately
(quickResult, verboseResult) = getResult(2)
print(quickResult) # Prints immediately
print(verboseResult()) # Prints after running the long-running function