Reputation: 49
I'm making a simple app that will spit out a random item from a list based on the category. I have two categories currently (places, and names). I'm trying to create two functions. One will return one of the categories randomly (working correctly) and one will take the random category and then randomly pull from the list for that category.
My problem is instead of the get_response
function returning a value from the list, it returns a random character from the name of the list it is getting as an argument. Any ideas on how to get around this. Thanks
Here is my code:
from random import randrange
types = ["places", "names"]
places = ["The Upper Room", "Jerusalem", "Church", "Rome"]
names = ["Jesus", "Desciples", "Paul"]
def get_random_type():
return str(types[randrange(0, len(types))])
def get_response(chosentype):
return chosentype[randrange(0, len(chosentype))]
randtype = get_random_type()
print(randtype)
print(get_response(randtype))
EDIT: Thank you everyone for your help! What a great community!
Here is my final working code. It is a combination of multiple answers.
import random
categories = ["places", "names"]
options = dict(places = ["The Upper Room", "Jerusalem", "Church", "Rome"],
names = ["Jesus", "Desciples", "Paul"])
def get_random_type():
return random.choice(categories)
def get_response(chosen_category):
category_items = options[chosen_category]
return random.choice(category_items)
print(get_response(get_random_type()))
Upvotes: 2
Views: 762
Reputation: 2762
randtype is a string not the list. You could do
print(get_response(eval(randtype)))
eval
function evaluates the “String” like a "python expression" and therefore eval(randtype)
is the list and not the string.
Upvotes: 1
Reputation: 836
Use a dictionary. Here's a fully functional working code that meets your requirement with least changes to make in your code.
from random import randrange
config = {
"places": ["The Upper Room", "Jerusalem", "Church", "Rome"],
"names": ["Jesus", "Desciples", "Paul"]
}
def get_random_type():
types = list(config.keys())
return str(types[randrange(0, len(types))])
def get_response(chosentype):
return config[chosentype]
randtype = get_random_type()
print(randtype)
print(get_response(randtype))
Upvotes: 2
Reputation: 19322
The issue is that in the first function you are passing a iterator (list) while in the second you are passing a string as iterator, so the string "places" is being used to get a random value from, which returns a character.
I would recommend using random.choice
and eval
function to solve this in a more elegant way -
import random
def get_random_type():
return random.choice(types)
def get_response(chosentype):
return random.choice(eval(chosentype))
randtype = get_random_type()
print(randtype)
print(get_response(randtype))
places
The Upper Room
So, if the first function chooses 'places', then eval
function over 'places' will return variable places
which is the list of places. Using another random.choice over that will give you a random place.
EDIT: As pointed out, eval
function may be dangerous as it can allow someone to write in a string of code as input forcing your app to run the code. HOWEVER, it's dangerous only if it's used irresponsibly. In this case, since the first function is forced to return a choice from a predefined list, the input to the second function is in safe hands. if you still want to ensure safety, you can do the following
def get_response(chosentype):
if chosentype in types:
return random.choice(eval(chosentype))
Please read about eval
, its misuse, and advantages if you plan to set this up as part of a webapp.
Upvotes: 1
Reputation: 56965
You can use a dictionary and random.choice
to first select a random item from the types
list, use that to key into the dictionary, then choice
again to pick a random item from the list you picked:
>>> from random import choice
>>> types = ["places", "names"]
>>> options = dict(
... places=["The Upper Room", "Jerusalem", "Church", "Rome"],
... names=["Jesus", "Desciples", "Paul"]
... )
>>> choice(options[choice(types)])
Desciples
In your original code, chosentype[randrange(0, len(chosentype))]
doesn't work because chosentype
is a string, so you're essentially doing:
>>> "foobar"[randrange(0, len("foobar"))]
'o'
which doesn't make much sense. If you want to stick with this design, you're stuck keying into globals as if it were a dictionary, or writing an if
-else
branch, neither of which is as good as the above solution.
Upvotes: 3