Reputation: 872
I am working on a machine learning modelling problem where an object is created to store training and validation data, but the validation set if optional and if not included when creating the object the default value is None
.
If we find out later on though the user wants to add a validation pandas dataframe we were hoping to let them supply the name of the dataframe with input()
. With a function defined right in the notebook we're running we can then do an eval(<input>)
to turn the string into the object we need. If we define the object outside of our notebook though it seems like the scope doesn't include that variable.
I realize this probably isn't the best way to do this, so what is a more pythonic way to let a user supply a dataframe by name after an object as already been instantiated? We can pass the objects fine as arguments to functions. Is there a way to pass an object like that but with input()
or some other user-friendly way to prompt the user?
Upvotes: 1
Views: 492
Reputation: 920
It maybe possible to use locals()
or globals()
as a dict
for grabbing an initialized variable by it's name.
the_variable = {'key_one': 'val_one'}
selected_input = input("Please input a variable name")
selected_var = locals()[selected_input]
print("selected_var continence -> {0}".format(selected_var))
Should output, well assuming the_variable
was passed to input()
selected_var continence -> {'key_one': 'val_one'}
This is an adaptation of an answer to Calling a function of a module by using it's name a string, but seems to work in this instance too.
I can't remember where I picked up the following perversion (I did look about though), and I'm not suggesting it's use in production. But...
questionable_response = lambda message: input("{message}: ".format(message = message))
this_response = json.loads(questionable_response("Input some JSON please"))
# <- '{"Bill": {"person": true}, "Ted": {"person": "Who is asking?"}}'
... does allow for object like input
ting.
And getting data from an input
ted json str
ing could look like...
this_response['Bill']
# -> {u'person': True}
this_response['Ted'].get('person')
# -> u'Who is asking?'
... however, you'll likely see some issues with using above with other scripted components.
For the Unicode conversion there's some pre-posted answers on the subject. And checking help(json.loads)
exposes that there's toggles for parse_
ing float
s, int
s, and constant
s.
Even with that it may not be worth it, because there's still some oddities you'll run into if trying to implement this funkiness.
Just to list a few;
conjunctions are a no go; let's say ya get a clever Clara who inputs something like '{"Clara": {"person": "I'll not be labelled!"}}'
. That would cause an error unless '
was escaped, eg. \'
the above is also quote fragile; perhaps someone at the keyboard hasn't had enough to drink and tries "{'Jain': {'person': True}}"
. That would first barf on quotes, then heave from True
not being true
So like I prefaced at the start of this update, I'll not recommend this in production; could waist a lot of time chasing edge-cases. I only share it because maybe you've not found any other option for getting from input
to something that can be interrogated like an object.
Upvotes: 1