Having a function that returns a list:
def func1(list1):
func1_result = list1 * 2 # This is just an illustrative example to simply show that the function returns a list resulting from any function calculation.
return func1_result
And getting the whole list returned by the function with:
Example 1:
list1_1 = [5, 4, 3, 2, 1]
print(f"{func1(list1_1)}") # "[5, 4, 3, 2, 1, 5, 4, 3, 2, 1]"
Or also getting the value of a specific index of the list returned by the function, with:
Example 2:
list1_1 = [5, 4, 3, 2, 1]
print(f"{func1(list1_1)[0]}") # "5"
Then, the question is about, is there any way where the function func1
could detect if the calling instruction syntax/format is including or not the indexing part [n]
? and also, when including the indexing part [n]
, then, how to know what specific index value is in the function calling instruction?
def func1(list1):
func1_result = []
'''
if the function calling instruction is about getting the whole resulting list:
do the function calculations to get the whole resulting list `func1_result`.
elif the function calling instruction is about getting one specific index value of the resulting list:
do the function calculations to get only the resulting value for the specified index.
# In this case the result could be a 1-element list.
# Main goal for this case: saving memory during calculations when working with large lists and with many function's calls.
'''
return func1_result
My understanding is that the indexing access specified in the calling instruction takes place after the function returns the resulting list, but maybe there would be a kind of way (ideally a direct way) which the function could get this calling format information from the calling instruction, without the need to specify it manually with an additional function parameter.
Having a function that returns a list:
def func1(list1):
func1_result = list1 * 2 # This is just an illustrative example to simply show that the function returns a list resulting from any function calculation.
return func1_result
And getting the whole list returned by the function with:
Example 1:
list1_1 = [5, 4, 3, 2, 1]
print(f"{func1(list1_1)}") # "[5, 4, 3, 2, 1, 5, 4, 3, 2, 1]"
Or also getting the value of a specific index of the list returned by the function, with:
Example 2:
list1_1 = [5, 4, 3, 2, 1]
print(f"{func1(list1_1)[0]}") # "5"
Then, the question is about, is there any way where the function func1
could detect if the calling instruction syntax/format is including or not the indexing part [n]
? and also, when including the indexing part [n]
, then, how to know what specific index value is in the function calling instruction?
def func1(list1):
func1_result = []
'''
if the function calling instruction is about getting the whole resulting list:
do the function calculations to get the whole resulting list `func1_result`.
elif the function calling instruction is about getting one specific index value of the resulting list:
do the function calculations to get only the resulting value for the specified index.
# In this case the result could be a 1-element list.
# Main goal for this case: saving memory during calculations when working with large lists and with many function's calls.
'''
return func1_result
My understanding is that the indexing access specified in the calling instruction takes place after the function returns the resulting list, but maybe there would be a kind of way (ideally a direct way) which the function could get this calling format information from the calling instruction, without the need to specify it manually with an additional function parameter.
Share Improve this question edited Jan 18 at 3:09 codev asked Jan 17 at 20:35 codevcodev 476 bronze badges 4 |1 Answer
Reset to default 3You can't do this in any reasonable way. The indexing instruction can't begin until the function returns a result, period.
The best you could do to achieve a result similar to this would be to have func1
actually be a class that stores its arguments without doing any work until a __getitem__
or __repr__
/__str__
or whatever call requires it to do some work. In specific cases, this might be an improvement in performance, the code is just more complicated.
Trivial example:
import collections.abc
from operator import index
class lazy_mapping(collections.abc.Sequence):
def __init__(self, list1):
self._list1 = list1
def __getitem__(self, idx_or_slice):
if isinstance(idx_or_slice, slice):
# Only do real work for elements from slice
return [do_real_work(x) for x in self._list1[idx_or_slice]]
# It's not a slice, do the real work for the single item indexed
return do_real_work(self._list1[idx_or_slice])
def __len__(self):
return len(self._list1)
def __repr__(self):
return repr(self[:]) # Represent the class as the repr of the list produced by applying the function
And it would be used exactly as you propose, with print(f"{lazy_mapping(list1_1)[0]}")
only performing the real work for index 0
, not the rest of list1_1
, and print(f"{func1(list1_1)}")
performing the complete mapping as part of producing the repr
. Inheriting from collections.abc.Sequence
means you can allow it to provide the fallback implementations for all the things that are straightforward and mostly boilerplate.
By performing the work in __getitem__
, you can limit it to the items actually requested. The risk is that they request data for many such elements, repeatedly, and now you're doing more work to optimize the "only want a single item" case at the expense of the "need the entire result (or multiple access to many elements)" case. A complicated result-caching algorithm could mitigate this, at the expense of even more complex code.
func1_result = []
before you reassign the variable? – Barmar Commented Jan 17 at 20:54return list1 * 1
with zero change in behavior, and if you assume the inputs are actually sequences (so numeric multiplication isn't actually something to handle), a simplereturn list1[:]
/return list1.copy()
/return list(list1)
(so many ways to shallow copy alist
!) would be even simpler/more straightforward. – ShadowRanger Commented Jan 17 at 21:13func1_result = []
and its only purpose was about the 2nd function code can run as is, as shown (in that situation returning an empty list because the needed commented part). So, the relevant part is about the function can have an efficient way to handle the situation when the calling instruction is to get only 1 specific element from a function that currently returns a resulting list. – codev Commented Jan 17 at 21:32return list1 * 1
. The current function workflow is about doing some calculation that obtains a list and then returning that list. – codev Commented Jan 17 at 21:48