luke bouch
luke bouch

Reputation: 49

Python returning character from list name instead of list item

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

Answers (4)

aerijman
aerijman

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

Saurav Pathak
Saurav Pathak

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

Akshay Sehgal
Akshay Sehgal

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

ggorlen
ggorlen

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

Related Questions