How to think like a Computer Scientist exercise - python

So as the title hopefully suggest, this is for an example in said book.
I'm still new to programming and having difficulty debugging. With that said any criticism is welcomed, specially if it shows a more efficient way of coding; just keep in mind that I'm still new so there's a good chance i might not know what you're referring to if you toss me a new built-in function or something.
So the point of this exercise is to write a function, giving it three arguments, to determine if those three arguments form a triangle. Here's my code:
def is_triangle(a,b,c):
num_list = [a,b,c]
biggest = max(num_list)
other_two = num_list.remove(biggest)
sum_of_two = sum(other_two)
if sum_of_two > biggest:
print 'Congrats, %d, %d, and %d form a triangle!' % (a,b,c)
elif sum_of_two == biggest:
print 'That forms a degenerate triangle!'
else:
print 'That does\'t make any sort triangle... >:['
def sides():
side1 = raw_input('Please input side numero Juan: ')
side2 = raw_input('Now side two: ')
side3 = raw_input('...aaaannnd three: ')
import time
time.sleep(1)
print 'Thanks >:]'
side1 = int(side1)
side2 = int(side2)
side3 = int(side3)
is_triangle(side1,side2,side3)
sides()
Whenever i run it, however, i get the following:
Traceback (most recent call last):
File "A:/Python/is_triangle.py", line 27, in <module>
sides()
File "A:/Python/is_triangle.py", line 25, in sides
is_triangle(side1,side2,side3)
File "A:/Python/is_triangle.py", line 5, in is_triangle
sum_of_two = sum(other_two)
TypeError: 'NoneType' object is not iterable
My guess is the sum_of_two line but i don't know what's wrong with it. Could someone help me debug this?
I spend a good hour rewriting it with out the built_in function (in various ways, bunch of ors everywhere). But it looked terrible and I'd rather learn to write this way.

The problem is the fact that remove modifies the underlying list - it doesn't return a new list. Change it to:
num_list.remove(biggest)
sum_of_two = sum(num_list)
To see exactly why this happens, try the following in IDLE:
>>> x = [1,2,3,4,5]
>>> x.remove(1)
>>> x
[2,3,4,5]

Sincenum_list.remove(biggest) returns None, Consider this instead
other1, other2, biggest = sorted(num_list)
sum_of_two = other1 + other2
It looks like the if block needs to be indented too
def is_triangle(a, b, c):
num_list = [a, b, c]
other1, other2, biggest = sorted(num_list)
sum_of_two = other1 + other2
if sum_of_two > biggest:
print 'Congrats, %d, %d, and %d form a triangle!' % (a,b,c)
elif sum_of_two == biggest:
print 'That forms a degenerate triangle!'
else:
print 'That does\'t make any sort triangle... >:['

You just made a very common mistake, a simple one. In Python, when a function causes a change in a data structure, it does not return the changed structure. Usually it returns None. If the function gets a new data structure or new value, it returns it.
So, str.lower() doesn't actually change a string; it returns a new string where the characters are lower-case. If you have some list named lst and you run sorted(lst), it doesn't change the list; it returns a new list that is sorted. But lst.sort() sorts the list in-place, so it doesn't return a reference to the list; it returns None.
In the comments below, #lvc pointed out that list.pop() removes a value from a list and returns the value. So, this is an example of a function that changes a data structure and returns something other than None, but it still definitely does not return a reference to the changed data structure.
The list.remove() function changes a list, and it returns None. All you need to do is change your function to use the same list for everything: first use the list to find the max, then remove the max value from the list, then pass the list to sum().
The reason Python does things this way is to obey the "Command/Query Separation" principle.
http://en.wikipedia.org/wiki/Command%E2%80%93query_separation

Related

I am unable to fetch an element from a list of dictionaries [duplicate]

This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Closed 8 months ago.
I have been working on this assignment for school and I just can't figure out what why I cant get this program to work properly. I am trying to get the program to allow the user to enter three animals. It is only allowing me to enter one. I know it has to do with my placement of the return statement in the make_list function but can't figure out how to fix it.
Here is my code:
import pet_class
#The make_list function gets data from the user for three pets. The function
# returns a list of pet objects containing the data.
def make_list():
#create empty list.
pet_list = []
#Add three pet objects to the list.
print 'Enter data for three pets.'
for count in range (1, 4):
#get the pet data.
print 'Pet number ' + str(count) + ':'
name = raw_input('Enter the pet name:')
animal = raw_input('Enter the pet animal type:')
age = raw_input('Enter the pet age:')
#create a new pet object in memory and assign it
#to the pet variable
pet = pet_class.PetName(name,animal,age)
#Add the object to the list.
pet_list.append(pet)
#Return the list
return pet_list
pets = make_list()
Your problem is, precisely, that you're putting the return statement inside the for-loop. The for-loop runs each statement in it for however so many times.. if one of your statements is a return, then the function will return when it hits it. This makes sense in, for example, the following case:
def get_index(needle, haystack):
for x in range(len(haystack)):
if haystack[x] == needle:
return x
Here, the function iterates until it finds where the needle is in the haystack, and then returns that index (though there's a builtin function to do this, anyways, list.index()).
If you want the function to run for however many times you tell it to, you have to put the return AFTER the for-loop, not inside it. That way, the function will return after the control gets off the loop
def add(numbers):
ret = 0
for x in numbers:
ret = ret + x
return ret
(though again, there's a builtin function to do this as well, sum())
You just need to return the pet_list outside of the for loop, so it will happen after the loop has finished running.
def make_list():
pet_list = []
print 'Enter data for three pets.'
for count in range (1, 4):
print 'Pet number ' + str(count) + ':'
name = raw_input('Enter the pet name:')
animal=raw_input('Enter the pet animal type:')
age=raw_input('Enter the pet age:')
print
pet = pet_class.PetName(name,animal,age)
pet_list.append(pet)
return pet_list
You have the return statement at the incorrect level of indentation. It should be at the same depth as the for statement. Having the return within the loop causes it to break out of the loop.
Remove one indent before the return.
You notice the for loop runs only once because the return statement is inside the if statement, within the loop
I've had a similar problem right now with my code:
Return the number of even ints in the given array. Note: the % "mod" operator computes the remainder, e.g. 5 % 2 is 1.
count_evens([2, 1, 2, 3, 4]) → 3
count_evens([2, 2, 0]) → 3
count_evens([1, 3, 5]) → 0
def count_evens(nums):
summary = 0
for i in nums:
if i % 2 == 0:
summary += 1
return summary
count_evens([2, 1, 2, 3, 4])
if you go to visualize execution and paste in my code http://www.pythontutor.com/visualize.html#mode=edit
Once I unindented it 8 spaces (same depth as the for statement), it ran multiple times and gave the correct output.
Your spacing is off. return pet_list is in the scope of the for loop.

How find the max of a list and then store the max in a new list

I am trying to find the max of the "rollList" and everything I have tried isn't working.I'm not very good with coding and the instruction my teacher gave me isn't very clear. I also have to reset "rollList" back to empty for each player and I am very confused.Please someone help.
import random
class Player:
def __init__(self,name ):
self.name = name
self.dice = []
def __str__(self):
return self.name
def roll_Dice(self):
rollDice = random.randint(1, 6)
return rollDice
rounds = 1
rollList = []
newplayer = []
newplayer.append(Player("CAT:"))
newplayer.append(Player("DOG:"))
newplayer.append(Player("LIZARD:"))
newplayer.append(Player("FISH:"))
for rounds in range(1,4):
print("-----------------")
print("Round" + str(rounds))
for p in newplayer:
print(p)
for x in range (4-rounds):
rollDice = random.randint(1, 6)
rollList.append(rollDice)
print(rollList)
max.pop(rollList)
print(rollList)
rollList.clear()
len(rollList)
The line max.pop(rollList) is fairly meaningless. It attempts to call the pop method of the built-in max function, which doesn't exist.
You can get the maximum by just calling max itself:
maxRoll = max(rollList)
If you want to remove that roll, you can (although it doesn't seem necessary, since you'll be clearing the list):
rollList.remove(maxRoll)
If you want to append the maximum to another list:
anotherList.append(maxRoll)
You can find the maximum of a list using max() function:
mylist = [1,2,4,5,6,7,-2,3]
max_value = max(mylist)
Now max_value is equal to 7. You can add this to a new list using append() method:
new_list = []
new_list.append(max_value)
then new_list will be [7]
I report some suggestions to resolve the error I suppose you have: AttributeError: 'builtin_function_or_method' object has no attribute 'pop'
Just change max.pop(rollList) to max(rollList).
Then you have a list of only one element because you are calling methods inside the for rounds in range(1,4): loop, without letting the list populate with other elements. You are calling also clear at each loop.
Also, the for x in range (4-rounds): it is not required, it's a nested loop.
You are printing the list of names without assign to each person the value of roll dice, so who's the winner?
Finally, you defined roll_Dice() as instance method of Person, so why not use it?
So, why not rollList.append(p.roll_Dice()) instead of:
rollDice = random.randint(1, 6)
rollList.append(rollDice)
Hope this can help.

Turning Python code into a function

I am new to Python functions and am just practicing on my end. I wrote some basic code that asks user for a number input, 9 times, and then outputs either True or False based on > 100 or < 100.
This code works fine:
list_1 = []
count = 0
while count < 10:
text = int(input('list a number:'))
if text < 100:
list_1.append(True)
else:
list_1.append(False)
count = count + 1
print(list_1)
Now I want to convert that into a function (using For loop instead, for something different). I tried a few versions and can't get it, nothing happens when i run this:
def foo():
list_1 = []
text = int(input('list a number:'))
for x in range(10):
if text > 100:
list_1.append(True)
else:
list_1.append(False)
return()
2 questions:
How do I write that function so it is actually useful and returns True or False?
Can someone show me a basic example of how using a function in this instance could be worthwhile? Like how could I separate it from the first piece of code so it's actually useful in a different way?
I'd like to branch out from just writing pieces of code, to organizing it in a more efficient way
Thanks
It looks like you have an error in your return value for foo().
Make sure you return the list out of your function. for example:
def foo():
list_1 = []
for x in range(10):
text = int(input('list a number:'))#this should be inside the loop
if text > 100:
list_1.append(True)
else:
list_1.append(False)
return(list_1) #you are passing list_1 after your for loop
bool_list = foo() #will pass return value in function
#print(list_1) this will throw an error!
print(bool_list) #bool_list was list_1 in foo()
Reading up on namespaces, it is critical for understanding funcitons. When you launch foo(), it will run its own code, but if you don't pass objects with a return value, you can't use it in other places.
Functions are absolutely essential for well maintained code. Anytime an operation is needed repeatedly, functions cut down on unnecessary lines of code. They also offer versatility when the same operation needs to be run many times but in slightly different ways. You could pass an argument through foo() specifying how many times you want to run through your for loop, for example.
There's an almost unlimited number of ways that you can use functions. The main driver in your decision is whether or not you can reuse functionality or if it simplifies your code. So in essence, can I build this into a building block is the question you should ask yourself.
So in your example, say you have to take input in several different scenarios or you have to maybe evaluate a number of lists and provide print output.
You could separate things based on that:
def take_input(list):
count = 0
while count < 5:
inputlist.append(int(input('list a number:')))
count += 1
def print_output(list):
outputlist = []
for input in list:
if input < 100:
outputlist.append(True)
else:
outputlist.append(False)
print(outputlist)
inputlist = []
take_input(inputlist)
print_output(inputlist)

Number of Odds and Evens in a List Function - Python

I am trying to create a function called "odd_even" which takes my already created list (named "nums") and determines the number of odd and even numbers, and then returns the variables to me. However when I run this code I get:
NameError: name 'odd' is not defined
How do I fix this? If you can give me any useful pointers on the "return" function that would also be greatly appreciated.
import random
def main():
nums = []
for x in range(10):
nums.append(random.randrange(1,26))
def odd_even(given_list):
odd = 0
even = 0
for x in given_list:
if x % 2 == 0:
even += 1
else:
odd += 1
return odd
return even
odd_even(nums)
print("List had ", odd, "odds and ", even, "evens.")
main()
You are doing 2 things wrong.
First, you are trying to return two values but on different lines. You cant do this, to do this, do so as a tuple:
def odd_even(given_list):
odd = 0
even = 0
for x in given_list:
if x % 2 == 0:
even += 1
else:
odd += 1
return odd, even
Second, you call the function but dont store the value(s) of return. So you need change:
odd_even(nums) to odd, even = odd_even(nums)
By trying to execute:
print("List had ", odd, "odds and ", even, "evens.")
The main() is looking for variables odd and even, but they dont exist in main(), they exist locally in odd_even() (hence why you are calling return as to return them to the calling function. The reason you only see an error with respect to odd is because it is the first variable in that print() that the interpreter encounters an error on.
The only way around this without correct use of return is to declare them as global. But that is a bad idea so don't do that, keep things local on the stack!
You have some syntactic errors. Python...unlike many programming languages is whitespace conscious. This means you need to be careful with your indentation and spacing. More traditional languages like Java and C use brackets {} to define a scope, and semicolons ; to figure out line termination.
Perhaps you copied it poorly, but from what I see, it appears as though you are defining the function odd_even() within the function main(). That is, the definition of odd_even() is tabbed to the right, which means that its definition is within the function main. I assume that you want main to call the function odd_even(). Thus, you must tab it back over to the left so that it is at the same indentation level as main().
For this reason I use horizontal lines (see below) to clearly outline the scope of functions. This is good for me when I write in Python because otherwise it can be very unclear where one function ends, and where another begins.
Also, it appears as though you have 2 return statements. If you want to return 2 values, you should encompass it within an object. To get around this, there are two simple solutions that come to mind. You can make the odd_even() function access global variables (not recommended)...or you can return an array (any number of values back) or a tuple (exactly 2, but this is python specific).
Below is an implementation of both:
import random
# Declare global variables outside the scope of any function
odd = 0
even = 0
#-------------------------------------------------------------------------------
def main():
nums = [1,2,3,4,5,6,7,8,9,10]
return_value = odd_even(nums)
# Get the individual values back
o = return_value[0]
e = return_value[1]
# You can use the global variables
print("List had ", odd, "odds and ", even, "evens.")
# Or you can get the array back
print("List had ", o, "odds and ", e, "evens.")
#-------------------------------------------------------------------------------
def odd_even(given_list):
# This means we are referencing the variables odd and even that are global
global odd
global even
# Loop through the array
for x in given_list:
if x % 2 == 0:
even += 1
else:
odd += 1
return [odd, even]
#-------------------------------------------------------------------------------
main()

return statement in for loops [duplicate]

This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Closed 8 months ago.
I have been working on this assignment for school and I just can't figure out what why I cant get this program to work properly. I am trying to get the program to allow the user to enter three animals. It is only allowing me to enter one. I know it has to do with my placement of the return statement in the make_list function but can't figure out how to fix it.
Here is my code:
import pet_class
#The make_list function gets data from the user for three pets. The function
# returns a list of pet objects containing the data.
def make_list():
#create empty list.
pet_list = []
#Add three pet objects to the list.
print 'Enter data for three pets.'
for count in range (1, 4):
#get the pet data.
print 'Pet number ' + str(count) + ':'
name = raw_input('Enter the pet name:')
animal = raw_input('Enter the pet animal type:')
age = raw_input('Enter the pet age:')
#create a new pet object in memory and assign it
#to the pet variable
pet = pet_class.PetName(name,animal,age)
#Add the object to the list.
pet_list.append(pet)
#Return the list
return pet_list
pets = make_list()
Your problem is, precisely, that you're putting the return statement inside the for-loop. The for-loop runs each statement in it for however so many times.. if one of your statements is a return, then the function will return when it hits it. This makes sense in, for example, the following case:
def get_index(needle, haystack):
for x in range(len(haystack)):
if haystack[x] == needle:
return x
Here, the function iterates until it finds where the needle is in the haystack, and then returns that index (though there's a builtin function to do this, anyways, list.index()).
If you want the function to run for however many times you tell it to, you have to put the return AFTER the for-loop, not inside it. That way, the function will return after the control gets off the loop
def add(numbers):
ret = 0
for x in numbers:
ret = ret + x
return ret
(though again, there's a builtin function to do this as well, sum())
You just need to return the pet_list outside of the for loop, so it will happen after the loop has finished running.
def make_list():
pet_list = []
print 'Enter data for three pets.'
for count in range (1, 4):
print 'Pet number ' + str(count) + ':'
name = raw_input('Enter the pet name:')
animal=raw_input('Enter the pet animal type:')
age=raw_input('Enter the pet age:')
print
pet = pet_class.PetName(name,animal,age)
pet_list.append(pet)
return pet_list
You have the return statement at the incorrect level of indentation. It should be at the same depth as the for statement. Having the return within the loop causes it to break out of the loop.
Remove one indent before the return.
You notice the for loop runs only once because the return statement is inside the if statement, within the loop
I've had a similar problem right now with my code:
Return the number of even ints in the given array. Note: the % "mod" operator computes the remainder, e.g. 5 % 2 is 1.
count_evens([2, 1, 2, 3, 4]) → 3
count_evens([2, 2, 0]) → 3
count_evens([1, 3, 5]) → 0
def count_evens(nums):
summary = 0
for i in nums:
if i % 2 == 0:
summary += 1
return summary
count_evens([2, 1, 2, 3, 4])
if you go to visualize execution and paste in my code http://www.pythontutor.com/visualize.html#mode=edit
Once I unindented it 8 spaces (same depth as the for statement), it ran multiple times and gave the correct output.
Your spacing is off. return pet_list is in the scope of the for loop.

Categories