I not very sure how to phrase the question subject...
I have 3 files laid out:
bank.py:
class Bank(object):
def __init__(self, money):
self.money = money
def currentMoney(self):
print "You currently have $%d" %self.money
def useMoney(self, money_use):
self.money = self.money - money_use
print "You used $%d" %money_use
self.currentMoney()
def getMoney(self, money_get):
self.money = self.money + money_get
print "You received $%d" %money_get
self.currentMoney()
event.py:
class Event(object):
def Event1(self):
print "Your dad needs money. Will you give him?"
decision = raw_input("Yes or No")
if decision == "Yes":
Bank.useMoney(500)
elif decision == "No":
print "Your father is sad"
else:
print "I do not know what are you talking about"
main.py:
import bank
import event
Bank = bank.Bank(1000)
Event = event.Event()
Event.Event1()
When I execute the code. I get the following error:
NameError: global name 'Bank' is not defined
Basically, what I would like to do is to use event.py to create a series of events that will affect the money, and I can use main.py to run different series of events.
Would you be able to enlighten me how to do this? Thank you!
As mentioned in the other answer, you need to import Bank in event.py
from bank import Bank
Having said that, looking at the code in event.py, you're going to run into another error on the line:
Bank.useMoney(500)
As useMoney() takes self as the first argument, so it needs to be run on a Bank instance rather than on the class itself (in Java-type speak, useMoney is an instance method, not a static method).
I think what your intent is is to have a Bank instance be contained inside Event, and then call useMoney on that whenever Event1 is called.
You need to import bank in event.py, and use
if decision == "Yes":
bank.Bank(...)
or you could use at the beginning of your event.py:
from bank import Bank
class Event(object):
...
Otherwise, Python cannot know that the Bank object is defined in the bank module when it loads the event module.
Related
So I am working on a project which basically is to program a Monopoly. I want to be able for a player to pay X amount to the bank and have the bank properly receive and add that amount to its own. I am working the player on a Tkinter interface in a different class to the bank. I have done the following:
In Class Card1, import the Bank class from bank.py
Program a function pay_bank() where I get the amount entered in the Entry field and discount it from the player's available money and send it to bank.
-Create a function receive_payment() in the Bank class where it receives the player's money and adds it to its own.
For some reason, it is not working so I need your help. Code below:
Class Card1:
def __init__(self):
self.amount = 1500
self.properties = {}
#nested functions to handle interface and it's events
def manage_player1_card(self):
def pay_bank():
to_bank = int(payBox.get())
if self.amount > to_bank:
payBox.delete(0, END)
self.amount -= to_bank
Bank().receive_payment(to_bank)
class Bank:
def __init__(self):
self.bank_total = 14580
def receive_payment(self, pay):
self.bank_total += pay
*Indentation might look wrong due to copy-pasting but it is just fine in my code. What do you see I am doing wrong?
Basically, the self.bank_total amount is not adding up every time I enter the amount. For example: if I enter 500, it should go up to 15180, but it stays the same at 14580. I have debugged but it doesn't change. How can I fix this? Thanks!
Try something like this:
def pay_bank(bank: Bank):
...
bank.receive_payment(to bank)
That way you are passing the bank as a parameter.
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.
I'm new to OOP and this is my first shot at creating a Python class. I am trying to make my 3 variables private and so that only the methods update the info (enforce encapsulation). It seems that if I remove the setters and getters methods from my class, it has no impact on my code (must be the initializer method doing the work?). What can I do to improve this? Thanks.
Edit- i've updated my code and removed the init. My getters are not working now.
#Instantiate a new Pet Instance.
myPet = Pet()
#Get input from user.
myPet.setName = input("Enter the pet's name: ")
myPet.setTypes = input("Enter the pet's type (Dog, Cat, Bird, etc.): ")
myPet.setAge = input("Enter the pet's age (in years): ")
while myPet.setAge.isalpha():
print()
print("Age cannot contain numbers. Try again.")
myPet.setAge = input("Enter the pet's age (in years): ")
#Call the showPetInfo module using new instanced object.
myPet.showPetInfo()
class Pet:
#Fields of the Pet Class.
__PetName = ""
__PetType = ""
__PetAge = ""
#Setter methods.
def setName(self,name):
self.__PetName = name
def setTypes(self,types):
self.__PetType = types
def setAge(self,age):
self.__PetAge = age
#Getter methods.
#property
def getName(self):
return self.__PetName
#property
def getType(self):
return self.__PetType
#property
def getAge(self):
return self.__PetAge
def showPetInfo(self):
print("\n \n \n \n")
print("Here is your pet's information. Your pet's name is {}, it is a {} and it is {} years old.".format(self.getName,self.getType,self.getAge))
main()
you are unfortunately right, they use to say setters/getters are contracts doing restriction for adults... (if I tell you "dont touch it" then you shoulntd touch it) but there is nothing restricting you and you can modify them!
same "feature" can be observed with "constants"... do in the jupyther or the terminal this
import math
math.pi = 1
a = math.pi
a
math.pi
and you will see that you now modified the constant pi value to 1
many sugest to usse properties but that is not a capsulation at all, that is just sugar syntax for the same "adults contract" IMHO :)
so to your question
What can I do to improve this?
document the code you are writing so the other part using it is aware about how the code, instances states in objects must be handled
I am working on am assignment for my programming class in which we have to take a blackjack program and add the option to bet.
This is the original program:
http://courses.ischool.berkeley.edu/i90/f11/resources/chapter09/blackjack.py
This works with no problems.
In the class BJ_Game I have added some code to collect bets
class BJ_Game(object):
def __init__(self, names):
self.players = []
for name in names:
player = BJ_Player(name)
self.players.append(player)
self.dealer = BJ_Dealer("Dealer")
self.deck = BJ_Deck()
self.deck.populate()
self.deck.shuffle()
# betting
def placing_bets (self, names):
self.total_bets=10
for name in names:
yes_no=input("The dealer bets 10.", name, "would you like to bet on this round? (y/n)")
if yes_no=="y":
player_bet=input(int("How much would you like to bet?:"))
else:
break
self.total_bets=player_bet+self.total_bets
return self.total_bets
(Sorry about the formatting, I'm new at this. In real life it's indented just like in the link)
The only other change I made was to add the bottom two lines to print the bets that the winner has won:
def win(self):
print(self.name, "wins.")
# awarding bets
print("You win $", self.total_bets)
When I run this, I get an error:
AttributeError: 'BJ_Game' object has no attribute '_BJ_Game__additional_cards'
I am not understanding how the changes I made caused this issue. Help is greatly appreciated.
Is this line:
def __additional_cards(self, player):
still in your program? If not, you have your answer. If yes, have a closer look at the code directly above this line.
I am very new to python. I am trying to learn by making a text based game.
In the gameplay I am wanting a variable, door_open, to begin false but once unlocked door_open = True. The next time the function is called a different message would be displayed.
door_open =False
def house():
print "The door is locked"
plan = raw_input(">")
if plan.lower() == 'use key':
inventory.remove("House Key")
door_open = True
print "You are inside"
start() ## this just returns to the starting point outside
if door_open == True:
print "You walk inside"
exit(0) ## using this until I develop it more
else:
print "Door is locked. Do you want to use your key (Y/N)?"
When Python sees an assignment to a variable in a function, when the variable is not marked as global (or nonlocal), it treats the variable as a new local variable.
Thus Python is treating the original code similarly to
door_open = False
def house():
if plan.lower() == 'use key':
door_open_LOCAL = True # only assigned here
if door_open_LOCAL == True: # whoops, might not be assigned yet!
pass
(That is, the local variable shadows the global variable, I've emphasized the point above by giving the local variable a different name entirely.)
See also:
Why some Python variables stay global, while some require definition as global
Use of "global" keyword in Python
If you want to write to a variable in the global scope you need to use the global keyword:
door_open = False
def house():
global door_open
print "The door is locked"
# ...
Also, please read and follow PEP8, the Python style guide. For example. you shouldn't use if foo == True: but if foo:
You are trying to track status of your game and got a bit lost in where is the status noted:
This is typical situation for using a class:
game.py:
import sys
class Game():
def __init__(self):
self.door_open = False
self.inventory = ["House Key", "Snow Gun", "Swiss army knife"]
def unlock_house(self):
assert "House Key" in self.inventory, "`House Key` must be present in inventory"
self.inventory.remove("House Key")
print "Click, Click"
self.door_open = True
def fireup(self):
print "Bufff"
self.inventory = []
def main():
game = Game()
while True:
# report current status
if game.door_open:
print "You are in the house!"
print "You are the King"
sys.exit(0)
else:
print "The door is locked!"
# ask for further plans
print "What is your further plan?"
plan = raw_input(">")
# change the situation
if plan.lower() == "use key":
game.unlock_house()
elif plan.lower() == "set up file":
game.fireup()
if __name__ == "__main__":
main()
You can see the split between the class Game, which is able to track the status and even do some changes of it, and the main piece of code, where you try to use the game somehow.
The class Game is sort of idea, how your notes about game status could look like.
Then in game = Game() you instantiate the class, get an object, and start doing real changes to the status.
Having status information stored in well designed and quite well isolated object is very convenient, you know, where to find what you need.