Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Call a def from a string
#1
I have a variable called "current" which is the name of the current def you are in. If you lose a life a new def is called. Since rooms are picked at random, I cant just use 'roomname()' to get back to the original room you were in before you lost a life. I need something that assignes current the as the current def name, then calls that variable in the death function like 'current()'.
I have tried this:
import inspect #this a test

def main():
    room1()

def room1():
    global current
    current = inspect.stack()[0].function
    dead()

def dead():
    current()

main()
but I get an error saying 'TypeError: 'str' object is not callable'

Any help on this would be appreciated!
Thanks, Dream.
Reply
#2
would you elaborate what you want to do? Maybe show more of your actual code...
This sounds really weird... It sounds like really wrong design - e.g. you can always keep the room name you are in (the one picked at random)
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
FYI def has a name it's 'function' or 'method' if part of a class.

This is best done by creating a class named Room. Then when you want a room, you instantiate a new class.

Dumb Example (but gets the point across (I hope):
class Room:
    def __init__(self):
        self.current = None

    def dead(self):
        self.current = 'Dead'
    
    def alive(self):
        self.current = 'Alive'

class MyGame:
    def __init__(self):
        self.den = Room()
        self.den.alive()
        self.kitchen = Room()
        self.kitchen.alive()

    def display_rooms(self):
        print('\nden is {}'.format(self.den.current))
        print('kitchen is {}'.format(self.kitchen.current))
    
    def play(self):
        print('In the beginning')
        self.display_rooms()
        self.den.dead()
        print('A while later')
        self.display_rooms()
        self.den.alive()
        self.kitchen.dead()
        print('\nIn the end: ')
        self.display_rooms()

if  __name__ == '__main__':
    game = MyGame()
    game.play()
results:
Output:
In the beginning den is Alive kitchen is Alive A while later den is Dead kitchen is Alive In the end: den is Alive kitchen is Dead
Reply
#4
Python types are dynamically assigned at runtime. You can change the type of a variable many times (not recommended) (e.g. from 'int', to 'float', to 'str', to 'float', ...). However current() is a function call. The Python interpreter in context knows current as type 'str', and you are trying to access current as a function, which is exactly the error message that you see.

We probably need a little more detail to give you a definitive answer to your question.

Lewis
To paraphrase: 'Throw out your dead' code. https://www.youtube.com/watch?v=grbSQ6O6kbs Forward to 1:00
Reply
#5
Small experiment

Output:
In [12]: import inspect #this a test ...: def main(): ...: room1() ...: def room1(): ...: global current ...: current = inspect.stack()[0].function ...: print(current, type(current)) ...: main() ...: ...: room1 <class 'str'>
reveals it all. You get a function name - not a function object. I am not sure that inspect module (have not touched it for a long time) is intended to pass function references

PS there's a way to use current as you intended - though I would not either call it healthy or recommend it
Output:
In In [14]: globals()[current] Out[14]: <function __main__.room1()>
I was not about to get my machine into endless mutual recursion (well, in 3.6 recursion stack depth is about 3000, so what the heck Think ), but adding brackets after the globals()[current] would have called the function room1
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#6
What about a dict of rooms, and you pick one from there?

import random

rooms = {}

def get_next_room_from(current_room):
    next_room = None
    while not next_room or next_room == current_room:
        next_room = random.choice(list(rooms.keys()))
    return next_room

def entryway():
    print("Welcome to the entryway.  Bye!")
    next_room = get_next_room_from("entryway")
    return next_room

def conservatory():
    print("This is the conservatory.  There's plants and wicker couches here.")
    next_room = get_next_room_from("conservatory")
    return next_room

rooms["entryway"] = entryway
rooms["conservatory"] = conservatory

running = True
current_room = "entryway"
while running:
    current_room = rooms[current_room]()
    running = "q" != input("Type 'q' to stop.").lower()
Reply
#7
So it makes more sense, I will post all my code here:
**I know that it is messy, (maybe)inefficient, and the use of certain aspects is bad.**

import random
import time
import sys
import inspect

Answer1 = ["Push Walls", "PUSH WALLS", "push walls", "Push walls", "push Walls"] #Array of all possible answers.
Answer2 = ["Red Green Yellow", "Red, Green, Yellow", "red green yellow", "Red green yellow", "red Green yellow", "red green Yellow", "red, green, yellow",
           "Red, green, yellow", "red, Green, yellow", "red, green, Yellow", "RED GREEN YELLOW", "RED, GREEN, YELLOW"] #Array of all possible answers.
Answer3 = ["Look Up", "look Up", "LOOK UP", "look up"] #Array of all possible answers.
lives = 3

a = 0 #
b = 0 #used to see if a room has already been picked. 0 is 'not picked' and 1 is 'is picked'
c = 0 #

#introduction
def intro():
    env = """
        """
    print(env)
    time.sleep(0.5)
    print("""
          """)
    time.sleep(0.5)

#main story
def main():
    intro() #introduction
    ######
    random.choice([room1,room2,room3])() #pick random room
  
    
def room1():
    global currentFuncName
    global a
    global lives #making lives global so it can be accessed from outoflives()
    a = 1
    currentFuncName = current = inspect.stack()[0].function
    #print(currentFuncName)
    time.sleep(0.5)
    print("""
         """)
    correct1 = input("")

    if correct1 in Answer1:
        print("")
    else:
        lives = 2
        outoflives()

def room2():
    global b
    b = 1
    print("")


def room3():
    global c
    c = 1
    print("")
    
  
#called if you lose
def lose():
    print("")
    time.sleep(2)
    main()

#called if you win
def win():
    print("")
    time.sleep(2)
    main()

def outoflives():
    global lives
    while lives != 0:
        time.sleep(0.3)
        print("")
        time.sleep(0.5)
        print("", str(lives), "")
        time.sleep(1)
        print("")
        currentFuncName()
        break
    while lives == 0:
        print("")
        lose()
        break
    
def roompick():
    if a == 1:
        random.choice([room2,room3])()
    elif b == 1:
        random.choice([room1,room3])()
    elif c == 1:
        random.choice([room1,room2])()
           
main()
As a brief overview, a random room is picked. a / b / c is set to 1. If you lose a life you go to outoflifes(). Then it uses currentFuncName() to call the previous function you were just in - room1() for instance. IF you pass taht room roompick() is called. depending on what room is set to 1 means you wont get that room again.

Nevermind I got this to work after lots of experimenting!
import inspect #this a test

def main():
    room1()
 
def room1():
    global current
    current = inspect.stack()[0].function
    dead()
 
def dead():
    print("dd")
    eval(current + '()')
    
main()
I know eval() should be avoided at all times but I have no user inputs in that area of my code.

Thanks for all the help!
Reply
#8
(Jun-23-2018, 08:21 AM)DreamingInsanity Wrote: I know eval() should be avoided at all times but I have no user inputs in that area of my code.
Thanks for all the help!


Why thank us, if you're ignoring almost every bit of advice that was sent your way? lol
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to call the values at the end of a text string? Dieselkaine 2 3,024 Jul-02-2018, 08:47 PM
Last Post: Dieselkaine

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020