NameError after importing a file - python

I have two files. One called "variables.py" with this function in:
def get_players():
'''
(NoneType) -> Dictionary
Asks for player names
'''
loop = True
players = {}
while loop == True:
player = input("Enter player names: ")
player = player.strip()
if player in players or player == "":
print("Choose a different name!")
elif "player1" in players:
players["player2"] = [player, 0]
elif player not in players:
players["player1"] = [player, 0]
if len(players) >= 2:
loop = False
return players
And another file in the same directory called "game.py" with this inside:
import variables
players = get_players()
When i try to run "game.py" i get this errorNameError: name 'get_players' is not defined
why?! I have tried everything!

It should be
players = variables.get_players()
Since you have imported only the module variables, and not the method get_players.
Or you could also do:
from variables import get_players
players = get_players()
Read more on importing modules here

You have imported variables, not get_players. You can either keep the import as it is and call variables.get_players(), or do from variables import get_players and then call get_players().
This is a fairly fundamental thing in Python: looks like you could benefit from a basic tutorial.

With Python, when you import a module, a module variable is created of that name which is where all the imported module's variables live:
import variables
players = variables.get_players()
You can also import from a module which will just introduce that name by itself:
from variables import get_players
players = get_players()
You can also do the following to import all names from a module, but it is discouraged because it leads to hard-to-read code:
from variables import *
players = get_players()

Related

Tried getting the Name from anothter python file but error index out of range

Tried Importing Name from File1 to File 2 so it can be used in Char1 creation but error as it state index out of range
Any ideas how can i get the name and roles from file 1 and input it in file 2 ?
Tested with File 1 that the name i input will get saved in the Name List when i tried printing it out but when i shift it over to File 2 its an empty list
File 1:
import pygame
import pygame_menu
import play
import PSB_Game
import random
Roles = [['WARRIOR'], ['TANK']]
Name = []
S_Role = []
def get_name(name):
Name.append(name)
print("my name is", name)
print(Name)
def get_role(role):
S_Role.append(role)
print('role is',role)
print(S_Role)
def main():
pygame.init()
surface = pygame.display.set_mode((800, 550))
menu = pygame_menu.Menu('Welcome', 800, 550, theme=pygame_menu.themes.THEME_BLUE)
menu.add.text_input('Character 1 Name:', onreturn= get_name)
menu.add.dropselect('Role:', Roles, onchange= get_role)
menu.mainloop(surface)
pass
if __name__ == "__main__":
main()
File 2:
import PlayerCreate
def main():
Char1 = warrior(200, 260, PlayerCreate.Name[0], 100, 5, 3, 'Warrior')
Char1_health_bar = HealthBar(100, screen_height - bottom_panel + 40, Char1.hp, Char1.max_hp)
run = True
while run:
clock.tick(fps)
#draw background
draw_bg()
#draw_panel
draw_panel()
Char1_health_bar.draw(Char1.hp)
#draw warrior
Char1.update()
Char1.draw()
#player action
if Char1.alive == True:
if current_Warrior == 1:
action_cooldown += 1
if action_cooldown >= action_wait_time:
#look for player action
# #attack
Char1.attack(Warrior1)
current_Warrior += 1
action_cooldown = 0
wanted to create a turn based battle game with the input for user for the char name and print them out
Problem
The problem occurs because you use the if __name__ guard that prevents the running of an entire script when it is imported. Running the PlayerCreate script on its own will run all the code, but only the unguarded parts of the script get executed when it is imported. Running the second script only will result in the creation of the global variables PlayerCreate.Roles, PlayerCreate.Name and PlayerCreate.S_Role and import the functions from the PlayerCreate script. The PlayerCreate.Name list is empty because that is how you instantiated it.
Solution
Changing the function name main into create in the PlayerCreate script and calling the function inside your main function of file 2 would be the cleanest solution. Otherwise, if you want the entire PlayerCreate script to be ran directly when it is imported, you could remove the if __name__ guard.

How to use variable from constructor inside of methode?

Hi guys hope u are doing well, i'm new with python :)
so i have two issues the first how can i use the variable name from the init to my function game() which it use two args (those args whose make it realy difficult for me !) as u can see in code bellow:
# FUNCTION.py
class penGame():
def __init__(self):
print("Welcome to Pendu Game")
self.name = input("Enter your name: ") # IMPORT THIS VARIABLE FROM HERE
def game(self, letter, rword):
letter = letter.lower()
if letter in rword:
for Id, Value in enumerate(rword):
if Value == letter:
donnee.default_liste[Id] = letter
else:
name2 = self.name # it deosn't work i got 1 missing arg when i run the code from MAIN.py
print(f"try again {name} it's wrong ")
print("-".join(donnee.default_liste))
The second issue is i need to use the same variable (name) from init in another module which is my main module and i couldn't use it cause i tried to create an object from class penGame() like:
myObject = penGame()
name2 = myObject.name
then use the name2 inside of the if condition as u can see bellow but it doesn't work properly cause it run the init again which is not what i want actualy !
any idea how can i did it plz?
#MAIN.py
import donnee
from fonctions import penGame
random_word = random.choice(donnee.liste_words) # creation of random word from liste_words
penGame() #call the constructor
while donnee.counter < donnee.score:
letter = input("Enter the letter: ")
if penGame.check(letter):
print("You cant use more one letter or numbers, try again !")
else:
penGame.game(letter, random_word) # as u can see that's the reason cause i supposed to send 3 args instead of two ! but i only need those two !!?
if penGame.check_liste():
myObject = penGame() # that's cause runing the init everytime !!
name2 = myObject.name
print(f"congratulation {name2} you've guessed the word, your score is: {donnee.choice-donnee.counter} point.")
break
if penGame.loser():
print(f"the word was {random_word.upper()} you have done your chances good luck next time.")
donnee.counter += 1
Thank u in advance hope u help me with that and excuse my english if it wasn't that good :) :)
1.Error
You're calling the methods on the class penGame, not on a instance of penGame.
This causes your missing argument error because the method needs an instance of the class (the self parameter) but don't get one.
Instead use your variable (from the second solution):
if mygame.check(letter):
print("You cant use more one letter or numbers, try again !")
else:
mygame.game(letter, random_word)
...
Replace penGame with mygame also in the other calls.
Error
Save the result of the call in a variable and you won't need to recreate it.
mygame = penGame() # call the constructor
This line can then be removed:
myObject = penGame() # that causes the init to run again because it creates a new instance!

Accessing Classes via Variable

I am attempting to make a small game, and what I will be doing is using classes to dictate the stats of the user's preferred class. I need to make the classes so when it comes time to fight a monster (which will also be in it's own class), I will be able to have their stats callable.
This may be a "big picture" problem, but to avoid writing the code three times (for each class), I only want to call the variable "chosenClass.HP" instead of "Mage.HP" because if I did it that way, I would need to have a bunch of if statements for each class among the story. There must be a better way.
I have worked on this both ways, and I hate having to write
if userChoice is 'Mage':
HP = 150
I have looked around at the self.something, but I don't completely understand how that works. If that is the required or recommended solution, what is the best resource for learning?
print("Welcome to the game")
name = input("Choose your name\n")
print(name)
class Warrior:
HP = 100
ATK = 200
DEF = 0
class Mage:
HP = 100
ATK = 200
DEF = 0
class Rouge:
HP = 150
ATK = 250
DEF = 100
user_class = input("Choose a class between Warrior, Mage, or Rouge\n")
print(user_class)
while(user_class != 'Warrior' and user_class != 'Mage' and user_class != 'Rouge'):
print("You did not choose from the required classes, try again")
user_class = input()
theClass = user_class()
theClass.HP = 1000
My error that I get from this code is:
TypeError: 'str' object is not callable
I understand it's being given a String, but it's a variable. Why is it causing problems?
Any recommendations to make this program better?
user_class returns a string and not an actual Class that you've defined above. This is because input() returns a string and you store that in user_class. In order to create a new instance of the classes you created in your code need to instantiate the class using some sort of logic based on the player's input such as:
if user_class.lower() == 'warrior':
theClass = Warrior()
theClass.HP = 1000
Obviously this wouldn't be the best way but is just an example to show how to instantiate the class.
You need a mapping of strings to classes if you want to create an instance like this.
pc_classes = {'Mage': Mage, 'Warrior': Warrior, 'Rogue': Rogue}
while True:
try:
user_class = input("Enter Mage, Warrior, or Rogue)
if user_class in pc_classes:
break
pc = pc_classes[user_class]()

Object only callable when "from" import used (Python)

Following an online tutorial, I typed up the following code:
class Car:
# define and initialize some attributes of Car object
def __init__(self):
self.speed = 0
self.odometer = 0
self.time = 0
# 'get' function for current speed
def say_state(self):
print("I'm going {} kph!".format(self.speed))
# 'set' function for current speed
def accelerate(self):
self.speed += 5
# 'set' function for current speed
def brake(self):
self.speed -= 5
# 'set' function for trip time and distance
def step(self):
self.odometer += self.speed
self.time += 1
# 'get' function for average speed
def average_speed(self):
return self.odometer / self.time
if __name__ == "__main__":
my_car = Car()
print("I'm a car")
while True:
action = input("What should I do? [A]ccelerate, [B]rake, "
"show [O]dometer, or show average [S]peed").upper()
if action not in "ABOS" or len(action) != 1:
print("I don't know how to do that.")
continue
if action == "A":
my_car.accelerate()
elif action == "B":
my_car.brake()
elif action == "O":
print("My car has driven {} kilometers".format(my_car.odometer))
elif action == "S":
print("My car's average speed was {} kph".format(my_car.average_speed()))
my_car.step()
my_car.say_state()
Then, I broke from the tutorial because it didn't tell me what the if __name__ == "main" business was about. Reading elsewhere, I kind of understood that this statement prevents the code following that if statement from executing if the module isn't being run as the main class, but rather is imported. So to test this out I typed up another small module "import_practice.py:
import Car
corolla = Car()
corolla.say_state()
This code would not run, with the error "Car is not callable", so I figured my import was wrong. I replaced import Car with from Car import Car and it worked, but according to the following answer, it shouldn't make a difference, right? In fact, if that answer is correct, it isn't the behavior I'm looking to get out of my import at all.
If you do this:
import Car
Then your code should be:
corolla = Car.Car()
corolla.say_state()
When you "import" a module, you are not bringing all its components to the current namespace. You are just loading it. If you want to refer to a component on that module, you must refer it through its module name: Car.Car. Here, first Car is the name of the module, and the second one is the name of the class.
If you actually want to import all module's components to the current namespace, you can do from Car import *. But I would not recommend that.
After that, you did from Car import Car. Here, the sentence is stating that you are bringing the name Car to the current namespace, from the Car module. Hence, you can just use Car on your code after this.
Please do note that the answer you are referring to is not saying that import Car is the same as from Car import Car.
The line
import Car
loads the module Car, and makes all the thing it declares (ie., the class Car) available inside the namespace Car.
The line
from Car import Car
loads the module Car (the from Car import part), then makes the name Car declared in that module (which is the class Car) available in the current namespace. That is,
import Car
Car.Car()
is equivalent to
from Car import Car
Car()
except for what the name Car in the global namespace refers to (the whole module, or just the one class).
Note that import statements also support as. With that you can change the name given in the current namespace:
import Car as CarModule
CarModule.Car()
and
from Car import Car as CarClass
CarClass()
also do the same thing as the other two, again except for names.
Import troubles
If you have a file called Car.py and you call import Car, that will add the entire module to the current scope.
import Car
print(dir(Car))
# [ ... 'Car' ]
This means you can also do things like:
# import the module and alias it
import Car as c
# add class to local scope as `Car`
Car = c.Car
On the other hand, if you use the from keyword, you are getting something in that module and adding it to the current scope:
from Car import Car
corolla = Car.Car()
corolla.say_state()
What is this __name__ == '__main__' nonsense?
When you call a file python <my-file-name> it sets the special variable __name__ to be the string __main__. if __name__ == '__main__' translates to "if someone is trying to run this as an independent script, then do the following". On the other hand, if someone calls import on that same file, that area will not trigger.

Picking random variable in list

I am trying to pick a random dictionary variable from a list. I start out by choosing a random variable from the list emotelist.
import random
emotelist = [bored]
emotechosen = random.choice(emotelist)
emotename = emotechosen['emote']
emoteframe = emotechosen['frame']
bored = {'emote':'bored', 'frame':135}
print emotename
print emoteframe
But I recieve an error of
NameError: name 'bored' is not defined
Thank you for the help. I should have defined my variables in the list before creating the list of variables.
You have to define bored before creating a list that holds it:
import random
# move bored definition here:
bored = {'emote':'bored', 'frame':135}
# now use it in a list construction
emotelist = [bored]
emotechosen = random.choice(emotelist)
emotename = emotechosen['emote']
emoteframe = emotechosen['frame']
print emotename
print emoteframe
You need to define bored before using it:
import random
bored = {'emote':'bored', 'frame':135}
emotelist = [bored]
emotechosen = random.choice(emotelist)
emotename = emotechosen['emote']
emoteframe = emotechosen['frame']
It looks like you are trying to print a random dictionary value:
from random import choice
bored = {'emote':'bored', 'frame':135}
print bored[choice(bored.keys())]

Categories