I apologize in advance for my confusing question.
I am attempting to write a simple text-based rpg for school, and I went into this with no prior knowledge of python or how to code in it. so after many youtube videos and tutorials and such, I got a pretty good base understanding. So one thing I wanted is for the character to have a name that you set just after the start. so to do this I did this
def character_namer ():
character_name = raw_input("please enter your name: ")
the problem is that now my variable 'character_name' can only be used within the def character_namer loop. How do I create a variable outside of that loop that represents 'character_name' so that any time I want to say the characters name I just type 'character_name'. Thanks.
Just return the value
def character_namer():
return raw_input("please enter your name: ")
character_name = character_namer()
print character_name
Either return the value within the function like what Paul Rooney suggested, or if you're inside idle or python shell simply do:
character_name = raw_input('please enter your name: ')
I'd say it's good practice to keep track of the game state in a class. Sure this might be a little over the top for "just" the character name, but it will be much more easy to extend and maintain.
class Game(object):
def __init__(self):
self.character_name = None
# eventually other important values
def ask_name(self):
self.character_name = raw_input('please enter your name: ')
def play(self):
self.ask_name()
print('Hello,' self.character_name)
# etc ...
game = Game()
game.play()
Related
In my project I have user made variables. What I'm trying to do is print the variable if the user gives a string named the same as the variable. Here's what I think it would look like:
variable = 123
userInput = input("Enter a variable to print: ")
print(userInput)
# Instead of printing userInput, it will check if userInput is the name of a variable,
# and print if it is.
The user will input "variable", and will print 123.
Also note that the variables will have their custom names and data. So if the variable name is something different, user entering "variable" won't cause it to be printed.
And yes, I know that having user-made variables can be a bad idea. I know what I'm doing.
You can access your variables dynamically by their name using globals():
print(globals().get(userInput,"No such variable"))
You can replace "No such variable" with any other default value in case the variable doesn't exist
You can create a userspace for each user with their own variables, i.e
def get_userspace(user):
""" Returns current userspace of user. """
# Here may be Postgres, Redis or just global userspaces
global userspaces
return userspaces.setdefault(user, {})
userspaces = {}
userspace = get_userspace(user)
then place all input of specific user in his/her userspace to not interfere with others and to not redefine locals/globals that can be viable for program execution. An then use your code with little improvements to get variable from that userspace:
user_input = input("Enter a variable to print: ")
print(userspace.get(user_input))
Here you go.
variable = 123
userInput = input("Enter a variable to print: ")
print(globals()[userInput])
so I've started learning python again and I'm currently making a mini movie-recommendator. I want my code to be a little bit more understandable so I'm always trying to use def to make the code simple. My problem is ;
def welcome():
print("""Welcome to the low budget film recommender!
Here you can tell me what kind of movies do you like or what movie did you watch
and I'll suggest you a movie from my database according to that.""")
name = input("But first I need to learn your name:>> ").capitalize()
print(f"Nice to meet you {name}")
return name
I want to use the name variable outside of the function(inside another function actually) but it gives me NameError and says "name" is not defined. How can I fix this and use the name variable outside of the function?
It's not best-practice to declare it as a global variable (as the other answers have recommended).
You should go to wherever welcome() is called and set a variable with the result (which you are returning inside welcome):
name = welcome()
print(f"This is the result of welcome: {name}")
You can declare the variable name as global variable.
Code -
def welcome():
global name
print("""Welcome to the low budget film recommender!
Here you can tell me what kind of movies do you like or what movie did you watch
and I'll suggest you a movie from my database according to that.""")
name = input("But first I need to learn your name:>> ").capitalize()
print(f"Nice to meet you {name}")
return name
def second_function():
welcome()
print(name) #prints the value of name in this function which was defined in the welcome()
second_function()
I have modified your code a bit and by using the name variable as a global variable you can achieve what you want. Have a look at the code
#name as a global variable
name = input("But first I need to learn your name:>> ").capitalize()
def welcome():
print("""Welcome to the low budget film recommender!
Here you can tell me what kind of movies do you like or what movie did you watch
and I'll suggest you a movie from my database according to that.""")
# name = input("But first I need to learn your name:>> ").capitalize()
print(f"Nice to meet you {name}")
return name
print(welcome())
def message():
return name
print(message())
Let me know if you still need any assistance
I am still working on the same encryption program before and I am currently stuck.
choice = ""
def program (str,my_fn):
global i
i=0
while i<len(str):
my_fn
i += 1
def encrypt(my_result):
message.append(ord(answer[i]))
while choice != "Exit":
choice = input("Do you want to Encrypt, Decrypt, or Exit?\n")
if choice == "Encrypt":
answer = input("What would you like to encrypt:\n")
message = []
program(answer,encrypt(message))
print (answer)
print (message)
So the first part of the program is simply asking the user if they wish to Encrypt, Decrypt, or Exit the program, this part works perfectly fine. However, my issue is with the functions. Function "program" is intended to serve as a repeater for the inner function for every single letter in the string. However, when I try to run the program, it continues to tell me that "i" isn't defined for the "encrypt" function and does nothing. I am certain I set "i" as a global variable so why isn't this working. In case you are wondering why I chose to make two functions, it is because I will later have to use function "program" multiple time and for this specific assignment I am required to use functions and abstractions. Thanks!
Add one line after your first line
choice = ""
i = 0
The keyword global means you declare an access to a global name.
Also, using a global variable is almost never a good idea. You may want to find another way to design your function.
The line program(answer,encrypt(message)) doesn't do what you want it to do. Rather than passing the function encrypt and its argument message to program (which can call it later), it calls the function immediately. It would pass the return value to program instead, but since encrypt(message) doesn't work without i defined, you get an exception instead.
There are a few ways you could fix this. By far the best approach is to not use global variables in your functions, and instead always pass the objects you care about as arguments or return values.
For instance, you could pass a function that encrypts a single letter to another function that repeatedly applies the first one to a string (this would be very much like the builtin map function):
def my_map(function, string):
result = []
for character in string:
result.append(function(character))
return result
def my_encryption_func(character):
return ord(character)
If you really want to stick with your current architecture, you could make it work by using functools.partial to bind the answer argument to your encrypt function, and then call the partial object in program:
from functools import partial
def program (str,my_fn):
global i
i=0
while i<len(str):
my_fn() # call the passed "function"
i += 1
def encrypt(my_result):
message.append(ord(answer[i]))
choice = ""
while choice != "Exit":
choice = input("Do you want to Encrypt, Decrypt, or Exit?\n")
if choice == "Encrypt":
answer = input("What would you like to encrypt:\n")
message = []
program(answer, partial(encrypt, message)) # pass a partial object here!
print (answer)
print (message)
I have written a simple menu function that i want to call from my main_program() function. The code also includes a class called Writing which I'm trying to make an object of inside the main_program(). The reason for this is that I've heard that it's preferable to avoid global variables. However this doesn't work and I get the answer: NameError: name 'writing_obj' is not defined
When I create the object outside the main_program() everything works fine so I guess is that I have to return my object writing_obj from the main_function() somehow?
Here is the code I wrote:
class Writing:
def writing_something(self):
print("I'm learning Python ")
def menu():
while True:
val = int(input("1. Write a sentence 2. Quit "))
if val == 1:
writing_obj.writing_something()
elif val == 2:
print("The program shuts down. See ya! ")
break
else:
print("Sorry, I din't get that! ")
continue
def main_program():
writing_obj = Writing()
menu()
main_program()
writing_obj is defined within the main_program() function and is not declared to be global. I would suggest using function arguments:
...
def menu(writing_obj):
...
def main_program():
writing_obj = Writing()
menu(writing_obj)
You could instead put global writing at the beginning of the main_program() definition, but as you said, global variables are not recommended.
I am currently making a game in Python. Whenever you want help in the game, you just type help and you can read the help section.
The only problem is, I need to add a function block for each level.
def level_01():
choice = raw_input('>>>: ')
if choice=='help':
level_01_help()
def level_012():
choice = raw_input('>>>: ')
if choice=='help':
level_02_help()
So I was wondering if is possible to make a global function block for all the levels?
When you enter help, you get to help(), and then it automatically goes back to the function block you just came from.
I really hope you understand what I mean, and I would really appreciate all the help I could get.
You can actually pass the help function as a paramater, meaning your code can become:
def get_choice(help_func):
choice = raw_input('>>>: ')
if choice == 'help':
help_func()
else:
return choice
def level_01():
choice = get_choice(level_01_help)
def level_02():
choice = get_choice(level_02_help)
Ideally you should have a separate Module for all interface related tasks, so that the game and interface will be two seperate entities. This should make those 2911 lines a bit more legible, and if you decide to change Interfaces (from Command Line to Tkinter or Pygame for example) you will have a much much easier time of it. Just my 2ยข
A really nice way to handle this kind of problem is with the built in python help. If you add docstrings to your function, they are stored in a special attribute of the function object called doc. You can get to them in code like this:
def example():
'''This is an example'''
print example.__doc__
>> This is an example
you can get to them in code the same way:
def levelOne():
'''It is a dark and stormy night. You can look for shelter or call for help'''
choice = raw_input('>>>: ')
if choice=='help':
return levelOne.__doc__
Doing it this way is a nice way of keeping the relationship between your code and content cleaner (although purists might object that it means you can't use pythons built-in help function for programmer-to-programmer documentation)
I think in the long run you will probably find that levels want to be classes, rather than functions - that way you can store state (did somebody find the key in level 1? is the monster in level 2 alive) and do maximum code reuse. A rough outline would be like this:
class Level(object):
HELP = 'I am a generic level'
def __init__(self, name, **exits):
self.Name = name
self.Exits = exits # this is a dictionary (the two stars)
# so you can have named objects pointing to other levels
def prompt(self):
choice = raw_input(self.Name + ": ")
if choice == 'help':
self.help()
# do other stuff here, returning to self.prompt() as long as you're in this level
return None # maybe return the name or class of the next level when Level is over
def help(self):
print self.HELP
# you can create levels that have custom content by overriding the HELP and prompt() methods:
class LevelOne (Level):
HELP = '''You are in a dark room, with one door to the north.
You can go north or search'''
def prompt(self):
choice = raw_input(self.Name + ": ")
if choice == 'help':
self.help() # this is free - it's defined in Level
if choice == 'go north':
return self.Exits['north']
A better solution would be to store the level you are on as a variable and have the help function handle all of the help stuff.
Example:
def help(level):
# do whatever helpful stuff goes here
print "here is the help for level", level
def level(currentLevel):
choice = raw_input('>>>: ')
if choice=='help':
help(currentLevel)
if ...: # level was beaten
level(currentLevel + 1) # move on to the next one
Sure, it's always possible to generalize. But with the little information you provide (and assuming "help" is the only common functionality), the original code is extremely straightforward. I wouldn't sacrifice this property only to save 1 line of code per level.