Hello people,
I'm currently working on a python module providing tools for co-workers to use and some of the functions I'm trying to provide can return quite a bit of useful information (say, 5 return values), but in most use case, only the first two will be needed.
I know python is great for writing highly dynamic programs especially since we can ask for informations about currently running system, so I though of searching a little, but I couldn't seem to find. (I found a lot of interesting discussion, but nothing actually discussing my issue.)
Is there a way, from within a function, to know the amount of expected return values ?
For instance, there could be the function:
def lazyOdd():
return 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21
Which would be called using one, three, five = lazyOdd()
.
Edit: Apparently it wasn't clear at all, what I seek looks like :
def lazyReturn():
return (val1, val2) if expectedReturns == 2 else (val1, val2, val3, val4)
I know that in this case, it definitely isn't the best way to proceed and almost any kind of iterable could do, but with values that aren't linked at all, it wouldn't be as simple. If possible, since most use case are going to be using only two results, I would like to avoid returning a big tuple, for many co-workers won't even know the function return the others values and it'll be quite error-prone.
Can I do that ?
Edit: Also, I don't mind if the solution includes some overhead, as I will most likely win a lot of time by not processing the last three values.
Edit²: Maybe the best way really is to pass another parameter specifying the amount of values expected ?
It's hard to tell from your description, but it seems that you need caching.
This way, you can write multiple functions. One is used for heavy calculations, the others output the correct format and number of values. If the heavy calculation is called a second time with the same input value, the previous result is returned.
from functools import lru_cache
@lru_cache(maxsize=32)
def heavy_common_calculation(x):
print("HEAVY CALCULATION FOR %d. Should only be done once!" % x)
result = x**2
return result
def get_two_values(x):
return x, heavy_common_calculation(x)
def get_four_values(x):
y = heavy_common_calculation(x)
return x, y, y**2, y**3
print(get_two_values(3))
# HEAVY CALCULATION FOR 3. Should only be done once!
# (3, 9)
print(get_four_values(3))
# (3, 9, 81, 729)
Do you want to implement a generator?
def lazyOdd():
x = 1
while True:
yield x
x = x + 2
odd_gen = lazyOdd()
print(next(odd_gen))
# 1
print(next(odd_gen))
# 3
print(next(odd_gen))
# 5
print(next(odd_gen))
# 7
If you want a value, it gets calculated. If you don't need it, nothing happens and nothing is calculated in vain.
len(odd_gen)
isn't defined because it would start an infinite loop.
You could use an argument to tell the function how many results you need:
def f(x, detail='low'):
a, b = x, x**2
if detail == 'high':
return a, b, 'something', 'else'
else:
return a, b
print(f(3))
# (3, 9)
print(f(3, detail='high'))
# (3, 9, 'something', 'else')