I have a question which is more about a general understanding of loops and case-structures. Therefor I will not deliver a runable code.
Is there somehow an option to iterate over objects of a function? I use a if-elif differentiation to call diffent files of a dataset.
Is it possible for the user of this function to make a request about all possible cases the programmer/data base manager offers in this function?
I try to better explain my question in an example:
Example of available datasets given in a if-else-structure (the user might not be aware of all possible choices that can be called):
def data(date):
if date == '20220318':
file = 'dataset_a'
return file
elif date == '20220317':
file = 'dataset_b'
return file
elif date == '20210712':
file = 'dataset_c'
return file
elif date == '20210708':
file = 'dataset_d'
return file
elif date == '20210621':
file = 'dataset_e'
return file
else:
raise Exception("Invalid date")
The result I am aiming at is a list of all "date"-objects like:
20220318
20220317
20210712
20210708
20210621
A direct iteration seems not to be possible like:
for date in data:
print(date)
This leads to TypeError: 'function' object is not iterable.
Is there a way to call all possible choises?
Thanks for helping to understand how loops really work.
CodePudding user response:
In answer to the question:
"Is it possible for the user of this function to make a request about all possible cases the programmer/data base manager offers in this function?"
The answer is yes. Below are listed two methods in particular, one 'messy' way, and another more robust way - but will require function re-factoring.
The messy way:
(Please do not use this in production code)
The advantage of this approach, is that you only require access to the function, and re-factoring is not required.
This approach uses the inspect
module to parse the function into text. Then, a regex pattern is used to extract the possible date
options, and returns these as a list.
import inspect
import re
# Define the regex pattern to extract the required values.
rexp = re.compile('date\s==\s\'(\d )\'')
# Get source code in plain text.
src = inspect.getsource(data)
# Extract date strings.
dates = rexp.findall(src)
Output:
['20220318', '20220317', '20210712', '20210708', '20210621']
The more robust way:
This approach will require re-factoring the function, but will likely serve better in the long term. (recommended)
Simply place all possible dates and their associated file in a dict
. Use the dict.get()
method to return the requested value, or a default string if the requested value is not found.
The function also features a return_dates_only
argument, which if passed as True
, returns the keys to the lookup
dictionary and provides the user with the valid options.
def data2(*, date: str=None, return_dates_only: bool=False):
lookup = {'20220318': 'dataset_a',
'20220317': 'dataset_b',
'20210712': 'dataset_c',
'20210708': 'dataset_d',
'20210621': 'dataset_e'}
if return_dates_only:
return list(lookup.keys())
else:
return lookup.get(date, '[Error]: Invalid date')
Note: The asterisk in the function declaration tells the function to accept keyword arguments only.
Usage:
>>> data(date='20220318')
`dataset_a`
>>> data(date='20220101')
'[Error]: Invalid date'
>>> data()
'[Error]: Invalid date'
>>> data(return_dates_only=True)
['20220318', '20220317', '20210712', '20210708', '20210621']
Comments:
In answer to the question:
"Can someone help me to understand why a concept like
for date in ...
cannot work?"
Per the __iter__
method's documentation:
This [an
__iter__ method
] is required to allow both containers and iterators to be used with thefor
andin
statements.
... which the data
function does not (nor can it) have.