Referencing a class member via a variable

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
togs
Newbie
Posts: 6
Joined: Wed Aug 18, 2021 6:12 pm
itch: togs
Contact:

Referencing a class member via a variable

#1 Post by togs »

Suppose I have a class named fruittypes, with members including apple, banana and cherry. There are attributes for name, shape, size and color.

I also have a function like this:

label fruitdata( fchoice):
"Your chosen fruit, the [fchoice.name], is typically [fchoice.size], [fchoice.shape] and appears in shades of [fchoice.color]."
return

Now, if I call the function like this:

call fruitdata( cherry )

It tells me a cherry is small, round and red.

Then I try this:

python:
fchoice = renpy.input( "What's your favorite fruit?", length = 8 )
... some stuff to strips spaces, standardize case, etc.

call fruitdata( fchoice )

I get an error saying 'unicode' object has no attribute 'name', because it's treating fchoice as if it were the class member, rather than what fchoice references.

Fairly new to this, so any help would be appreciated!

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2438
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: Referencing a class member via a variable

#2 Post by Ocelot »

togs wrote: Thu Aug 19, 2021 3:59 am Suppose I have a class named fruittypes, with members including apple, banana and cherry. There are attributes for name, shape, size and color.
I assume it is used like this:

Code: Select all

define cherry = Fruittypes("cherry", "small", "round", "red")
define apple_g = Fruittypes("apple (Granny Smith)", "medium", "round", "green")
# . . .
# other fruits
togs wrote: Thu Aug 19, 2021 3:59 am Then I try this:

python:
fchoice = renpy.input( "What's your favorite fruit?", length = 8 )
... some stuff to strips spaces, standardize case, etc.

call fruitdata( fchoice )

I get an error saying 'unicode' object has no attribute 'name', because it's treating fchoice as if it were the class member, rather than what fchoice references.

Fairly new to this, so any help would be appreciated!
Lets start with line call fruitdata( fchoice ). When you used call fruitdata( cherry ), you passed a reference to object of type Fruittypes and specific content. Now you are passing fchoice, which is something returned by renpy.input and processed. renpy.input returns a string — a type (called unicode internally) containing characters you can manipulate, replace, etc.
So, to speak, fruitdata label expected to be passed an actual fruit, but got a list of paper wuth fruit name written on it. When it tries to do things it can do with a fruit with a piece of paper, it couldn't. Hence the error.

What can you do?

* First of all, you can set up some code which takes string, compares it with predefined strings and calls fruitdata with correnct fruit. This is high maintenace, annoying to extend, DRY-violating route, we won't do that.

* Second, you can try to get a member of store variable based on string your player enters. This is viable solution, but I prefer next one.

* Third, you can store your fruits in some data type where you can look up any fruit by its name. Such data type is called Dictionary in Python:

Code: Select all

# Simplest way
define fruits = {
    "cherry": Fruittypes("cherry", "small", "round", "red"),
    "apple": Fruittypes("apple (Granny Smith)", "medium", "round", "green"),
}
# . . .
# input stuff
if fchoice in fruits: # Need to check if this is a fruit we know, otherwise we get another error
    fchoice = fruits[fcoice] # Replace string in fchoice with actual fruit
    call fruitdata( fchoice ) # Print fruit data
else:
    "I do not know anything about fruit called [fdata]"

# If you prefer your fruits to still be defined as separate variables you can do that:
define cherry = # . . .
define apple_g  = # . . .

define fruits = {
    'cherry': cherry.
    'apple': apple_g,
}

# Or even
define fruits = {f.name: f for f in [cherry, apple]}
Last edited by Ocelot on Thu Aug 19, 2021 8:23 am, edited 1 time in total.
< < insert Rick Cook quote here > >

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Referencing a class member via a variable

#3 Post by Remix »

... or reference the string inside the store scope...
togs wrote: Thu Aug 19, 2021 3:59 am
python:
fchoice = renpy.input( "What's your favorite fruit?", length = 8 )
... some stuff to strips spaces, standardize case, etc.

call fruitdata( getattr(store, fchoice) ) ### <<--- getattr
Frameworks & Scriptlets:

togs
Newbie
Posts: 6
Joined: Wed Aug 18, 2021 6:12 pm
itch: togs
Contact:

Re: Referencing a class member via a variable

#4 Post by togs »

Thank you all - I appreciate all the suggestions - going to go away and experiment!

Post Reply

Who is online

Users browsing this forum: Google [Bot]