Управление количеством возвращаемых переменных в функции
Есть ли способ определить функцию, которая знает, сколько переменных вернуть, основываясь на том, сколько результатов ожидает пользователь?
Позвольте мне проиллюстрировать идею. Предположим, следующая функция:
def function():
a = 1
b = 2
c = 3
return a, b, c
Тогда я бы хотел, чтобы моя функция вела себя так:
>>> x = function()
>>> x
1
>>> x, y = function()
>>> x
1
>>> y
2
>>> x, y, z = function()
>>> x
1
>>> y
2
>>> z
3
Есть ли в Python функция или концепция, которая может помочь мне достичь этого? Может быть, декораторы?
Любая идея приветствуется!
PD: Мой уровень Python все еще очень прост.
РЕДАКТИРОВАТЬ:
В настоящее время я перехожу из IDL в Python. Так что мне не хватает приятной функции в IDL, которую вы можете выбрать, чтобы возвращать столько переменных, сколько пожелаете, выполнив:
FUNCTION function, a=a, b=b, c=c
a=1
b=2
c=3
RETURN, a
И тогда вы можете просто спросить, что вы хотите получить обратно
IDL> x=function()
IDL> print, x
1
IDL> x=function(y=b)
IDL> print, x
1
IDL> print, y
2
IDL> x=function(y=b, z=c)
IDL> print, x
1
IDL> print, y
2
IDL> print, c
3
4 ответа
Вместо того, чтобы возвращать разные значения, вы можете назвать это по-другому:
x, *_ = function()
x, y, *_ = function()
x, y, z, *_ = function() # *_ is optional here if it only returns 3 things
При этом все неиспользуемые возвращаемые значения назначаются _
переменная, поэтому, если вы хотите, чтобы они получили gc'd рано, вы должны del _
,
Вы можете вернуть только один объект. Обратите внимание, ваша функция возвращает tuple
, Тем не менее, Python поддерживает синтаксис, который позволяет гибко распаковывать переменные
x,_,_ = function()
Или же
x,y,_ = function()
Или даже с расширенной распаковкой:
x, *_ = function()
Обратите внимание, используя _
в качестве одноразовой переменной это просто соглашение.
Несмотря на то, что Pythonic отличается от распаковки, вы можете создать декоратор и указать допустимое количество возвращаемых значений:
def filter_results(val):
def outer(f):
def wrapper(*args, **kwargs):
v = f(*args, **kwargs)[:val]
return v[0] if len(v) == 1 else v
return wrapper
return outer
@filter_results(1)
def function():
a = 1
b = 2
c = 3
return a, b, c
r = function()
Выход:
1
Полные результаты:
@filter_results(2)
def function():
...
x, y = function()
И, наконец:
@filter_results(3)
def function():
...
x, y, z = function()
Если не считать безумных уловок, таких как проверка байт-кода вашего вызывающего, чтобы увидеть, сколько значений он ожидает, это невозможно: интерпретатор не примет любое несоответствующее количество значений (он проверяет и перехватывает дополнительные значения).