I am trying to write a program about poker game and for the comparison part I called (returned) multiples values for each set up.
In this case, I returned an array, one of them was a boolien and one of them was an integer. But when I tried to use them in another function I get an error ('bool' object is not subscriptable) and I dont know why. My whole code is nearly 150 line and for running it you ll need extra file so I ll share some parts of it.
these are the set up parts for each combination
def straight(n):
F = converter(n)
if consecutive(F) == True:
return [True, F[0]]
return False
def full_house(n):
F = converter(n)
if len(set(F)) == 2:
for i in F:
if F.count(i) == 3:
return [True, i]
return False
this is the part where I will rank them
def ranking(n, k):
if n == "AKQJT" and flush(k) == True:
return 9
elif straight(n)[0]== True and flush(k) == True:
return [8,straight(n)[1]]
elif four_kind(n)[0]== True:
return [7,four_kind(n)[1]]
elif (full_house(n))[0]== True:
return [6,full_house(n)[1]]
elif flush(k) == True:
return 5
elif (straight(n))[0]== True:
return [4,straight(n)[1]]
for example when I try
print(ranking("44447","DDDDD"))
I get an error
elif straight(n)[0]== True and flush(k) == True: line ...
TypeError: 'bool' object is not subscriptable
But interstingly when I try the straight flush (the second elif part tests it). For example,
print(ranking("23456","DDDDD")
I get an answer like
[8,6]
which its the true answer but then again I get the same error.
In the default case, you do not return an array:
return False
Change it to something like
return [False, None]
or whatever makes sense for your situation.
Please checkout what you are returning through straight(n). I believe in this case you are trying to return False. So, Boolean is not subscript-able.
If you get get straight(n) as False. You cannot write if-elif conditions to verify their cases. You need to design nested loops for cases straight(n) is False and straight(n) is not equal to False.
Related
For example,
[1,3,3,5] should return True while [1,3,1,3] should return False.
I am looking for a simple solution using loops.
I tried the following:
def conseq(nums):
for i in range (len(nums)):
if nums[i]==nums[i+1]:
return True
break
else:
return False
The first time your function encounters 2 consecutive numbers which are different, it returns False. Returning from a function ends that function immediately, the function does not continue after that. This is also why the break is not necessary.
Another issue with your code is that once you reach the final number, nums[i + 1] will access out of the bounds of the array. That's why you should iterate over len(nums) - 1 rather than len(nums) - there's no reason to check the final number because there's nothing after it.
def conseq(nums):
for i in range(len(nums) - 1):
if nums[i]==nums[i+1]:
return True
# Only return False once we've exhausted all numbers.
# Since we didn't return True so far - it means there are
# no consecutive equal numbers, so we can safely return False
return False
the return ends the function, so here it will stop the processing as well
your true statement mostly works, and the break is unnecessary
you don't want the else statement until after the for loop ends (it returns False only if everything else has been parsed)
Also the way you parse through the code, nums can't access nums[i+1] when you're at the final nums so you need the range len(nums) - 1
If you feel like putting an else that does nothing, you can with a single semicolon or pass I believe, but the else is unnecessary here
def conseq(nums):
for i in range (len(nums)-1):
if nums[i]==nums[i+1]:
return True
else:
;
return False
You can't return False until the loop is done (since the match may be in the part of the list you haven't checked yet). And the break after return will never happen (since return ends the function and everything in it).
Enumerate list without last (to avoid try catch for i+1 being out of range) then compare each item with next one and return True if they are same. After loop return False because none are similar consequtively (returns break functions)
def function(number_list):
for i, item in enumerate(number_list[:-1]):
if item == number_list[i+1]:
return True
return False
def conseq(nums):
for i in range (len(nums)):
if nums[i]==nums[i-1]:
return True
return False
I modified your Code. Please check and let know if useful
def conseq(nums):
flag=True
for i in range (len(nums)-1):
if nums[i]==nums[i+1]:
print(True)
flag=False
break
else:
continue
if(flag):
print(False)
nums=[1,3,3,5]
nums1=[1,3,1,3]
conseq(nums)
conseq(nums1)
We have many solutions here already. I have tried out using numpy without a loop:
>>> import numpy as np
>>> f = np.array([1,3,3,5])
>>> (np.where(np.diff(f) == 0)[0]).astype('bool')[0] #check if we have any difference of two elements 0?
True
I wrote this Python code that would check a list and return True if two items in the list next to each other are of the same value:
def samer(nums):
for i in range(0,len(nums)-1):
if (nums[i]) == (nums[i+1]):
return True
else:
return False
Result 1:
>>> samer([1,3,44,5,5,8])
False
This is where I'm puzzled because I feel it should return True.
Result 2:
>>> samer([3,3,49,93,5,8])
True
It only returns True if the first and second number in the list is True.
The solution:
def samer(nums):
for i in range(0,len(nums)-1):
if (nums[i]) == (nums[i+1]):
return True
return False
The above code works well, so my question is since the else statement indented under the if condition's purpose is to return False if no number in the list is next to each other in the process of the for loop, why do I still get False in Result 1?
Is it that it doesn't loop again after checking the first two boxes and why is that since it's the purpose of the for loop to go over each iteration and then check for the conditions?
When a function returns, that's it. The function is done, over, finished..
Since you're returning either true or false when checking each and every element, you really only check the first time through the loop (elements one and two), as you observe.
You should return true if a match is found and only return false at the end, when you've checked everything and, therefore, no matches are found. That code is already in your question, the bit under The solution.
So to chip in here, once that first iteration check occurs, we know that it's going to be returning False as the first two elements are not the same and the program ends there. If you want to really see that this is the case, make use of print() built-in function to see what's going on everytime the element is iterated within the for loop:
Like this:
def samer(nums):
for i in range(0,len(nums)-1):
if (nums[i]) == (nums[i+1]):
print(True)
else:
print(False)
### adding a main method is always a good idea for clarity.
if __name__ == "__main__":
print(samer([1,3,44,5,5,8]))
Output is this:
False
False
False
True
False
See it returned True for the 3th element as they are equal and next to each other.
But with the way you had it structured in the first example it does return False as it hit the roadblock once it checked and saw that the first iteration were not equal to each other and thus returned False.
def samer(nums):
for i in range(0,len(nums)-1):
if (nums[i]) == (nums[i+1]):
return True
else:
return False
if __name__ == "__main__":
print(samer([1,3,44,5,5,8]))
Output is:
False
With your solution approach which is great, the loop only 'terminates' when it really cannot find a match (same two numbers), it will return False without depending on a else statement. So if it finds a match then it will return True which is does and then stops iterating and exits the program.
I am writing an for loop comparing the character in list and string, then return False if the character is not same. But I keep receiving True. Can someone explain what is wrong with my code?
def compare (sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)+1):
if orig[i] == sofar[i]:
return True
else:
return False
return False
here is the result i got:
In [29]: compare (['a','v','c','c','s'], 'abccs')
Out[29]: True
But it suppose to be False
You could just join the characters back into a string
def compare (sofar, orig):
return ''.join(sofar) == orig
Otherwise, if you wanted a loop, you need to compare all characters before you return True. You can return False when the first does not match
Here's another one liner using all() over a loop of zipped characters.
You will need the length check before this statement
return all(x == y for x, y in zip(sofar, orig))
Or going back to the original code, invert your logic
def compare (sofar, orig):
if len(sofar) != len(orig):
return False
for i in range(len(orig)):
if orig[i] != sofar[i]:
return False
return True
If your function reaches a return statement, that's it. Your function has returned a value and it will not continue running.
You can use a generator to implement your logic. The below solution allows you to iterate lazily; retrieve a Boolean list with a letterwise comparison via list; or check if all letters align via all.
def compare(sofar, orig):
if len(sofar) == len(orig):
for i in range(len(orig)):
if orig[i] == sofar[i]:
yield True
else:
yield False
res = list(compare(['a','v','c','c','s'], 'abccs'))
# [True, False, True, True, True]
res = all(compare(['a','v','c','c','s'], 'abccs'))
# False
Another way of writing your logic without explicit iteration:
lst = ['a','v','c','c','s']
mystr = 'abccs'
res = ''.join(lst) == mystr
The statement return is exit from your function.
So your prog only compares the first element.
if orig[i] != sofar[i]:
return False
would do it
I'm new to programming so this is probably a silly question!
I'm trying to write a function that takes a list of letter grades and returns a Boolean true or false depending on whether it is a passing grade
## Calculate total units passed
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
else:
if letterGrade == 'NCN':
passed = False
else:
if letterGrade == 'WN':
passed = False
else:
True
return passed
unitsPassed = map(unitPassed,courseGradeLetter)
I've attempted to do this by creating a function that tests if a grade is a passing grade, and then map this over a list of grade.
The problem is that I get the following error for a list that contains more than one element:
local variable 'passed' referenced before assignment
If I try it with a list containing one element I get the correct result.
Any ideas why this is?
Thanks.
--
Thanks everyone, your answers have helped me a lot!
Some have already pointed your error and posted the most pythonic solutions, but anyway - here's another code review, but this time a step by step one:
First point: learn to use elif instead of nesting if clauses in else clauses:
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed
As you can see this is already more readable.
Second point: in Python we favor "early returns" - ie, in this kind of tests, instead of setting a variable in all branches and returning it at the end, we return directly (which avoids elif/else chains etc):
def unitPassed(letterGrade):
if letterGrade == 'N':
return False
if letterGrade == 'NCN':
return False
if letterGrade == 'WN':
return False
return True
Which makes the code even more straightforward.
And of course the last refactoring is to avoid the multiple tests when possible, as posted by Dadep and digitake (but using a tuple instead of a list because we dont need the overhead of a list here):
def unitPassed(letterGrade):
return letterGrade not in ("N", "NCN", "WN")
Also, you are using map() in your code snippet but while map() is still perfectly valid and appropriate, the more idiomatic (and marginally faster) version here would be a list comprehension:
passed = [unitPassed(letter) for letter in courseGradeLetter]
And since unitPassed is now basically a simple short expression, you can just inline it (unless of course you need this function elsewhere):
passed = [letter not in ('N', 'NCN', 'NWN') for letter in courseGradeLetter]
how about this
def unitPassed(letterGrade):
return letterGrade not in ['N', 'NCN', 'WN']
unitsPassed = map(unitPassed,courseGradeLetter)
you can redefine your function as :
>>> def unitPassed(letterGrade):
... GP=['N', 'NCN', 'WN']
... if letterGrade in GP:
... return False
... return True
...
>>> letterGrade='DE'
>>> unitPassed(letterGrade)
True
>>> letterGrade='NCN'
>>> unitPassed(letterGrade)
False
The error is in the 3rd else statement, i.e. in line 13.
Change True to passed = True
Also, you can make your function clean,
def unitPassed(letterGrade):
if letterGrade == 'N':
passed = False
elif letterGrade == 'NCN':
passed = False
elif letterGrade == 'WN':
passed = False
else:
passed = True
return passed
def is_prime(x):
if x < 2:
return False
elif x == 2:
return True
for i in range(2,x):
if x % i == 0:
return False
break
else:
return True
The above code is mine from codecademy's python course, and i get a prompt telling me that when 9 is passed to the argument, the function returns True instead of False. I can fix this by doing:
for i in range(2,x):
if x % i == 0:
return False
break
return True
I don't understand why the second bit of code works, and why the first bit doesn't. In fact, I would have thought the second bit of code wouldn't work: If the argument was 9, then when i == 3, x % i == 0. So the function gets a returned value of False, and the loop breaks. However, since the "return True" is NOT within the for loop, then after exiting the for loop, "return True" will execute anyway, so regardless of the input, the function will get returned a value of True, since that's the last line of code to be executed within the function?
Following that line of reasoning, I believed that my initial code would work, because if "return True" was within the for loop, then the break command would be executed (assuming the input was 9), AFTER the function has been returned a value of False. And since the "return True" line is within the the for loop, and since the break command will exit the for loop, then the last value given to the function would have been False, which would have been correct?
I apologise in advance if I have (very likely) misused certain terms, of have some flaw in my understanding of how the code works or is executed. I just can't seem to get my head around why the second bit of code works, but the first bit doesn't.
Cheers!
The for loop starts with i == 2. 9 % 2 == 1, so it goes into the else: branch, and returns True.
Only if the entire loop is run and none of the numbers divided 9 should you return True.
Also, following return ... by break is useless - the function has already returned, so that break statement is never reached.
That's also the answer to your last question -- when return is executed, this function ends. Nothing else is done anymore, and the program continues (returns to) wherever it was when it called the function.
The first version didn't work because , when ever the if condition is false it returns True.Thus, when x==9 and i==2, 9%2!=0, thus it returns true. Also, no need to use break statement as return statement returns the value from function and loop doesn't continue after return.
Following is the correct code
def is_prime(x):
if x < 2:
return False
elif x == 2:
return True
for i in range(2,x):
if x % i == 0:
return False
return True