code runs else statement repeatedly - python

every time the below code runs, it goes straight through to the first else statement, then runs the next else statement four times. what is going on and how do I fix it so it calls the movement() module?
class square(object):
def __init__(self,updown,leftright,residence,name):
self.updown = updown
self.leftright = leftright
self.residence = bool
self.name = name
a1 = square(1,1,True,"a1")
a2 = square(2,1,False,"a2")
b1 = square(1,2,False,"b1")
b2 = square(2,2,False,"b2")
square_dict = {a1:"a1",a2:"a2",b1:"b1",b2:"b2"}
movement_select()
def movement_select():
response = raw_input("where would you like to move?")
if response in square_dict:
moveTo = square_dict[response]
else:
print "this runs once"
for a in square_dict:
if a.residence == True:
moveFrom = a
movement(moveFrom,moveTo)
else:
print "this runs four times"
movement_select()

Look at how you're defining residence:
self.residence = bool
So, for any square a, a.residence will be the type bool, never the boolean value True (or anything else). So this test will always fail:
if a.residence == True:
To fix it, change that first line to:
self.residence = residence
While we're at it, you rarely need == True, so you can also change the second line to:
if a.residence:
But that isn't a necessary fix, just a way of simplifying your code a bit.
Meanwhile, your squares_dict is a bit odd. I'm not sure whether it's incorrect or not, but let's take a look:
It maps from square objects to their names. That could be a useful thing to do. It means you can iterate over the dict and get all the squares—as you correctly do in your code. And if you later had a square and wanted to get its name, you could use square_dict for that. Then again, you could probably get the same benefit with just a square_list, and using the name already available as an attribute of the square objects (unless you need the same square to have different names in different contexts).
And meanwhile, a mapping in this direction can't be used for looking up squares_dict[response], because response is a name, not a square. So, you definitely need a mapping in the opposite direction, either in addition to or instead of this one.
If you scrap the square-to-name mapping and only keep the name-to-square mapping, you can still iterate over the squares; you'd just have to do for square in squares_dict.values(): instead of just for square in squares_dict:.

First problem: your dictionary appears to be backwards: you want to look up the square objects from their locations, rather than the other way around. This is why your first conditional is never true. You also might as well strip() the response to ensure that you don't have any hidden whitespace in there.
square_dict = {"a1":a1, "a2":a2, "b1":b1, "b2":b2}
# Later...
response = raw_input("where would you like to move?").strip()
# Later still...
for a in square_dict.values(): # Because we switched the dictionary around!
If you don't want to silently strip off the whitespace, I'd suggest that you at least echo their input back to them (print('"{}"'.format(response))) in the case that it's not found in your dictionary, so they (you) can be sure that at least the input was correct.
The second problem is because of how you define residence. You set the variable equal to bool, which is not what you want at all. Line five ought to read:
self.residence = residence
Finally, some other thoughts on your code! You check whether a value is True by checking if a.residence == True:. The preferred form of this comparison is the simpler version:
if a.residence:
Your methods could also be named more descriptively. Generally speaking, it's always nice to begin a function or method name with a verb, to improve readability. This is of course a question of style, but for instance, the two functions we see, movement_select and movement aren't extremely clear as to their function. It would be much easier to read if they used a standardized form, e.g. choose_move and perform_move.

self.residence = bool
should be
self.residence = residence

You don´t set residence right, this is wrong:
class square(object):
def __init__(self,updown,leftright,residence,name):
self.updown = updown
self.leftright = leftright
self.residence = bool
self.name = name
it has to be
class square(object):
def __init__(self,updown,leftright,residence,name):
self.updown = updown
self.leftright = leftright
self.residence = residence # not bool!!
self.name = name

Your response contains \n symbol, just strip() it
You should also swap places between keys and values in your dictionary

Related

How do I affect the contents of multiple dictionaries or objects iteratively from within a loop?

I'm trying to use a pen-and-paper RPG system I know as a springboard for learning Python. I want to be able to use an object to represent a character, with all the stats that implies. I'm trying to use for and while loops to do things like determine number of actions per turn (based on individual speed) and the actions they take. My problem is that I can't figure out how to refer to the object within the loop so that Python goes through and sequentially affects each of the objects the way I'd want.
class char:
counter = 0 #char counter to keep track of the nbr of doodz
Asidecounter = 0
Bsidecounter = 0
def __init__(self,name,side,Spd,cSPD,DEF,HP,cHP):
self.name=name
self.side=side
self.Spd=Spd
self.cSPD=cSPD
self.DEF=DEF
self.HP=HP
self.cHP=cHP
char.counter+=1
if self.side == "a":
char.Asidecounter+=1
else:
char.Bsidecounter+=1
activechars.append(name)
activechars=[]
defeatedchars=[]
Okay, this gives us a character and some stats. (I tried to omit some extra stats here.) I have a counter for which side they're on, a total character count and so on every time I add a character to the mix. The problem is, then I want to determine the total # of moves available to be distributed among however many characters, I try to do something like this and it just doesn't work for me:
movecount=0
for i in range(len(activechars)):
movepick = activechars[i]
movecount+=movepick.Spd
You can see where I'm going here. I'd like to do something similar for attacks, special powers usage, whatever--put it in a loop but then call (and change) object-specific values from inside the loops, and I just don't know how to.
I've tried this with dictionaries instead of defined "char" objects; e.g.
hero={"Spd":4,"cSPD":4,"DEF":8,"HP":10,"cHP":10}
...and then rewrite the loops for a dictionary instead. But it's not working either way.
(Also, I've been told that I don't follow Python capitalization conventions, for which I apologize.)
You're so close, it appears to be a small issue. Running your code and created char objects, I noticed you're saving the object's name attribute only into the list - for instance, "lancelot" instead of something like <__main__.char at 0x1e5770a9f48>. Simply change the last line to append self instead of name (also check indentation).
class char:
counter = 0 #char counter to keep track of the nbr of doodz
Asidecounter = 0
Bsidecounter = 0
def __init__(self,name,side,Spd,cSPD,DEF,HP,cHP):
self.name=name
self.side=side
self.Spd=Spd
self.cSPD=cSPD
self.DEF=DEF
self.HP=HP
self.cHP=cHP
char.counter+=1
if self.side == "a":
char.Asidecounter+=1
else:
char.Bsidecounter+=1
activechars.append(self)
activechars=[]
defeatedchars=[]

Unsure of how to use attributes and methods in python

I am currently working on an assignment where in a particular question I have to take a list of playing cards and, using a class, figure out if it is a Royal Flush.
The lecturer provided a 'skeleton' of code that I have to build the rest around without changing the parts he wrote.
#Lecturer created...
class PokerHand(Hand):
def __init__(self, cards = list()):
Hand.__init__(self, cards)
self.handRank = 0
self.hand = "High Card"
#I have so far added this part...
total_value = 0
val_card_b4 = 0
for card in self.cards:
if Card.getValue(card) > val_card_b4:
total_value += Card.getValue(card)
val_card_b4 = Card.getValue(card)
checkRoyalFlush()
#...to here. However it throws an error that checkRoyalFlush isn't defined.
#The lecturer then had what is below already added.
def checkHand(self):
if self.checkRoyalFlush():
self.handRank = 9
self.hand = "Royal Flush"
print("Test")
I have already created a Card class in an earlier question that allows me to create a card object get the value of the card (A=11, 2-10 equal face value etc.)
My problem is that, once I have checked the cards, I don't know how to 'activate' the if self.checkRoyalFlush(): statement in the checkHand Method.
The code I have to get running is:
h1 = PokerHand([Card('hearts', '10'), Card('clubs', '10'),Card('hearts', '2'),Card('hearts', '3'),Card('spades', 'J')])
h1.show()
print(h1.checkHand())
I would like to understand how to get the if statement working, as I have spent a lond time researching and can't figure it out. I am only a beginner in python and new to the Object Oriented side of it.
Edit: I also don't know how to define 'checkRoyalFlush' without it getting more errors
An if statement such as if self.checkRoyalFlush(): requires a boolean data type as a result, i.e. True or False. Your method needs to return either one of those values:
#Lecturer created...
class PokerHand(Hand):
def __init__(self, cards = list()):
# etc...
def checkHand(self):
# etc...
# add your new method below the methods that already exist
def checkRoyalFlush(self):
# paste your code to check if it is a royal flush here
# if it is a royal flush, then:
return True
# if it is NOT a royal flush, then:
return False
Also you need to refer to your method as self.checkRoyalFlush() as it is a part of the class PokerHand. You aren't doing that in checkHand() method.
It looks like your lecturer want method called checkRoyalFlush() which I'm assuming will return true if your hand is a royal flush or false if it isn't aren't.
Also note that I don't know how you set up your card class, and I don't know what you are calling the suit or value attribute. In the code below, I call .suit for the suit attribute and .value and the value attribute. Change it to whatever you made it as.
Consider code below:
class PokerHand:
def __init__(self, cards = list()):
#your init goes here as above
def checkHand(self):
#checkHand as above
def checkRoyalFlush(self):
check_suit = cards[0].suit #note I don't know what you are calling the suits and values in your hand,
values = ['A','K','Q','J','10'] #values we want to check against
for each_card in cards:
if not (each_card.typing == check_suit and each_card.value in values):
return False
values.remove(each_card.value) #once we found a value we want to remove it from the possible list
return True
The method checkRoyalFlush() will take one card's suit out of the cards list. Since a royal flush must have all the same suit it doesn't matter which card I choose. Here I choose the first card in the list.
Then I iterate through the cards list and check if NOT each of the card's typing is the same, and if each of the values are in the values list
if one card is does not match the requirement, it returns False.
We remove the value we checked so we can make sure it's 1 value and not duplicated values.
If the for loop checking is finished with out returning False, we know that it's a royal flush
Note this is not the most optimal way to do it, it's just one way that shows how it can be done rather clearly.

How to create a list containing names of functions?

I am completely new to python and programming but I am trying to learn it using more practical approach.
What I am trying to do is an exercise for converting different units, e.g. pounds -> kilograms, foot -> meter etc.
I have defined all the functions for different unit pairs:
def kg_to_g(value):
return round(value*1000.0,2)
def g_to_kg(value):
return round(value/1000.0,2)
def inch_to_cm(value):
return round(value*2.54,2)
def cm_to_inch(value):
return round(value/2.54,2)
def ft_to_cm(value):
return round(value*30.48,2)
etc.
and created a list with names of these functions:
unit_list = ['kg_to_g','g_to_kg','inch_to_cm','cm_to_inch',
'ft_to_cm','cm_to_ft','yard_to_m','m_to_yard',
'mile_to_km','km_to_mile','oz_to_g','g_to_oz',
'pound_to_kg','kg_to_pound','stone_to_kg','kg_to_stone',
'pint_to_l','l_to_pint','quart_to_l','l_to_quart',
'gal_to_l','l_to_gal','bar_to_l','l_to_bar']
The program should randomly choose a unit pair(e.g. kg->pounds) and value (e.g. 134.23), and the user will be asked to convert those values.
random_unit = random.choice(unit_list)
lower = 0.1001
upper = 2000.1001
range_width = upper - lower
ranval = round(random.random() * range_width + lower, 2)
When user enters answer, the program should compare answer with the calculations defined by function and tell user if it is a correct answer or wrong answer:
def input_handler(answer):
if answer == random_unit(ranval):
label2.set_text("Correct!")
else:
label2.set_text("Wrong!")
Unfortunately, that way program doesn't work, and codesculptor(codesculptor.org) returns with an error
TypeError: 'str' object is not callable
Could someone please explain to me what is wrong with the code and suggest something to solve the problem.
Because you've enclosed the function names (in the list) in quotes, they have become strings.
Change your list to:
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch,
ft_to_cm, cm_to_ft, yard_to_m, m_to_yard,
mile_to_km, km_to_mile, oz_to_g, g_to_oz,
pound_to_kg, kg_to_pound, stone_to_kg, kg_to_stone,
pint_to_l, l_to_pint, quart_to_l, l_to_quart,
gal_to_l, l_to_gal, bar_to_l, l_to_bar]
And now it is a list of functions, which can be called like this: unit_list[0](34), for example.
So now random_unit(ranval) should not throw an exception.
Note also that comparing floats (if answer == random_unit(ranval)) will most likely cause you problems. See Is floating point math broken? for some detailed explanations of why this is.
As you are rounding you may get away with it, but it's good to be aware of this and understand that you need to deal with it in your code.
I think this is what you are asking about. You should be able to store the functions in a list like this
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch, ft_to_cm]
You can then call each item in the list and give it a parameter and it should execute the function for example like this:
unit_list[0](value)

Using if result more than once

I have a piece of code below which will skip functions dependent on a result. In a function, I have an if found statement, that will make the result true and run through the code below under if. I also have if not found in the function, which will set the result to False, so that the code inside the if statement below is skipped.
while repeatchoice == True:
code = getproductcode()
product = checkfile(code)
result,stocklevel = checkstocklevel(code)
if result:
quantity = quantityFunction(product)
checkquantity = isquantityokay(quantity, stocklevel)
quantity = int(quantity)
update = updatestocklevel(quantity, stocklevel, code)
cost = price(product)
productcost = calculateproductcost(cost, quantity)
rline = receiptline(product, quantity, productcost)
addtoreceipt = append(rline)
addtototal = appendprice(productcost)
repeatchoice = repeat(username)
I already have 'if result' in this code, and I need to do the same for another result (skip or run certain functions based on if result is returned true or false)
Is this possible using the variable 'result?'
I am already using 'if result' can I do this again?' So, would it be possible to have another 'if result' under where I am defining the quantity function?
I think you're asking if you can do this:
result = some_function1()
if result:
do()
some()
things()
result = some_function2()
if result:
do()
some()
other()
things()
Yes. You can do that. The value stored within result changes and is evaluated more than once as the flow of control proceeds.
If this is confusing to you, it may be you are confusing the different programming models imperative and declarative.
To over simplify, in declarative if you had the same declaration twice (foo = 1234 and foo = 5678), it could be considered a conflict because it would not be clear which is the intended definition. In declarative order usually doesn't matter. With imperative order and flow of control makes it clear which value foo holds.
That being said, you should try these things. Make a small test and see what happens. Python is a great language for experimenting.

FastQ programming error

So I'm trying to parse a FastQ sequence, but I'm a beginner to Python, and I'm a little confused as to why my code isn't working. This is what the program is supposed to carry out:
if I enter the FASTQ seqname line...
#EAS139:136:FC706VJ:2:2104:15343:197393
...then the program should output:
Instrument = EAS139
Run ID = 136
Flow Cell ID = FC706VJ
Flow Cell Lane = 2
Tile Number = 2104
X-coord = 15343
Y-coord = 197393
Here's my unfinished code thus far:
class fastq:
def __init__(self,str):
self.str = inStr.replace ('#',' ').split (':')
def lists (self,parameters):
self.parameters = ("Instrument","Run ID","Flow Cell ID","Flow Cell Lane","Tile Number","X-coordinates","y-coordinates")
def zip (self,myZip,zippedTuple):
self.Zip = zip(self.parameters,self.transform)
self.zippedTuple = tuple(myZip)
print (tuple(myZip))
def main():
seq = input('Enter FastQ sequence:')
new_fastq = fastq(str)
new_fastq.lists()
new_fastq.zip()
main()
The reason that your code isn't working is that it's more-or-less entirely wrong. To address your errors in the order we reach them when trying to run the program:
main:
new_fastq = fastq(str) does not pass the seq we just input, it passes the built-in string type;
__init__:
Calling the argument to fastq.__init__ str is a bad idea as it masks the very built-in we just tried to pass to it;
But whatever you call it, be consistent between the function definition and what is inside it - where do you think inStr is coming from?
lists:
Why is this separate to and not even called by __init__?
Why don't you pass any arguments?
What is the argument parameters even for?
zip:
Rather than define a method to print the object, it is more Pythonic to define fastq.__str__ that returns a string representation. Then you can print(str(new_fastq)). That being said;
Again, you mask a built-in. On this occasion, it's more of a problem because you actually try to use the built-in inside the method that masks it. Call it something else;
Again, you put unnecessary arguments in the definition, then don't bother to pass them anyway;
What is self.transform supposed to be? It is never mentioned anywhere else. Do you mean self.str (which, again, should be called something else, for reasons of masking a built-in and not actually being a string)?
myZip is one of the arguments you never passed, and I think you actually want self.Zip; but
Why would you create x = tuple(y) then on the next line print(tuple(y))? print(x)!
Addressing those points, plus some bonus PEP-008 tidying:
class FastQ:
def __init__(self, seq):
self.elements = seq.replace ('#',' ').split (':')
self.parameters = ("Instrument", "Run ID", "Flow Cell ID",
"Flow Cell Lane", "Tile Number",
"X-coordinates", "y-coordinates")
def __str__(self):
"""A rough idea to get you started."""
return "\n".join(map(str, zip(self.parameters, self.elements)))
def main():
seq = input('Enter FastQ sequence: ')
new_fastq = FastQ(seq)
print(str(new_fastq))
main()

Categories

Resources