Python function returning a weird string - python

I've been working through a book called Exercises for Programmers as I am trying to learn Python.
https://pragprog.com/book/bhwb/exercises-for-programmers
At exercise 8 I ran into some trouble; I am meant to write code that prompts for how many people wanna order pizza, how many slices each and then it must calculate how many pizzas must be ordered (1 pizza = 8 slices) according to the total number of slices (persons * slices each) and the number of leftover slices (if there are any).
I think I've managed to suss it out except that once executed the method that calculates the number of leftover slices prints a weird string (it also contains a hex value?).
I've modulated everything into two files (trying to build good habits);
file 01:
main.py
import pizza as p
while True:
number_of_people = input("How many people are hungry for pizza? ")
number_of_slices_per_person = input("And how many slices per person? ")
try:
val = int(number_of_people) or int(number_of_slices_per_person)
print("\n" + number_of_people + " people have ordered " +
str(p.number_of_pizzas(number_of_people, number_of_slices_per_person)) + " pizzas.")
if int(number_of_slices_per_person) == 1:
print("Each person would like just a " + number_of_slices_per_person + " slice of pizza.")
else:
print("Each person would like " + number_of_slices_per_person + " slices of pizza.")
print("There are " + str(p.number_of_leftover_slices) + " pizza slices left over.")
break
except ValueError:
print("Please enter a valid number")
file 02:
pizza.py
def number_of_pizzas(p1, s1):
"""Calculates the number of pizzas according to the specified
requirements"""
total_pizzas = 0
total_slices = int(p1) * int(s1)
for s2 in range(0, total_slices):
if s2 % 8 == 0:
total_pizzas = total_pizzas + 1
return total_pizzas
def number_of_leftover_slices(total_pizzas):
"""Calculate the number of leftover slices of pizza"""
import main as m
total_pizzas = total_pizzas
leftover_slices = (int(total_pizzas) * 8) %
int(m.number_of_slices_per_person)
return leftover_slices
And this is the output I get;
'4 people have ordered 2 pizzas.'
'Each person would like 3 slices of pizza.'
'There are < function number_of_leftover_slices at 0x7f0a95e2c7b8 > pizza slices left over.'
My issue is the string that gets printed instead of the number I am expected to have calculated. Any thoughts on what I might have done wrong?
Thanks.

You have two problems. Firstly, you need to indent the return line at the end of number_of_leftover_slices
Next, when you call print on an object, Python will try to use either the _repr_ or _str_ method of that object to get a string representation of that object. What you're seeing is the string representation of your number_of_leftover_slices function. What you want to print is actually the output of that function.
n = p.number_of_pizzas(number_of_people, number_of_slices_per_person)
remain = p.number_of_leftover_slices(n)
print(remain)

Related

First if statement being ignored by python but not elif's

Beginner in python here. I'm trying to create a program that takes the takes the total price of many things and rounds them up or down depending on their last digit. My issue is that my first "if" statement always gets ignored but all my other "elif" statements work just fine
Code:
if str(finalTotalPrice).endswith("1" or "2") :
roundedDown = round(finalTotalPrice, 1)
print("Final Total = $" + str(roundedDown) + str(0))
print()
cashPayment = float( input("How much cash will you pay with? $"))
change = (cashPayment - roundedDown)
change = round(change, 3)
print("Your change is $" + str(change))
elif str(finalTotalPrice).endswith("8" or "9") :
roundedUp = round(finalTotalPrice, 1)
print("Final Total = $" + str(roundedUp) + str(0))
print()
cashPayment = float( input("How much cash will you pay with? $"))
change = (cashPayment - roundedUp)
change = round(change, 3)
print("Your change is $" + str(change))
elif str(finalTotalPrice).endswith("5" or "0") :
print("Final Total = $" + str(finalTotalPrice))
print()
cashPayment = float( input("How much cash will you pay with? $"))
change = (cashPayment - finalTotalPrice)
change = round(change, 3)
print("Your change is $" + str(change))
Python is not natural language. and and or do not behave the way you are used to. Let's look at the documentation:
>>> help(str.endswith)
Help on method_descriptor:
endswith(...)
S.endswith(suffix[, start[, end]]) -> bool
Return True if S ends with the specified suffix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
suffix can also be a tuple of strings to try.
Your if statements should look like this:
if str(finalTotalPrice).endswith(("1", "2")):
As pointed out by tripleee, you're actually trying to do logically the wrong thing.
roundedDown = round(finalTotalPrice, 1)
This suggests that finalTotalPrice is a float. Never use floats for money. It'll mostly work for small values, but one day things will stop adding up. Instead, use an integer representing the amount of the smallest denomination you have – here, it looks like your dollar is divided into mils (you used round(..., 3)), so a dollar should be represented as 1000.
But can you still use the round function?
>>> help(round)
Help on built-in function round in module builtins:
round(number, ndigits=None)
Round a number to a given precision in decimal digits.
The return value is an integer if ndigits is omitted or None. Otherwise
the return value has the same type as the number. ndigits may be negative.
Yes, you can; just put in -1 to round to the nearest 10, -2 to round to the nearest 100, etc..
str(finalTotalPrice).endswith("1" or "2")
Ignoring the bug for a moment, this is a bad solution. If you're using floats, it will usually give a completely wrong answer, and if you're using ints it's inefficient. Once you're using ints, you can fix this; finalTotalPrice % 10 will get the last digit, finalTotalPrice % 100 will get the last two digits, etc.. Then you can do:
if finalTotalPrice % 10 in (1, 2):
if finalTotalPrice % 10 > 7:
if finalTotalPrice % 5 == 0:
as necessary.
Additionally, your cash payment code is identical in each if branch, so it should be written after them, not in each branch. And, while we're at it, let's make your variable names conform to PEP 8, the Python Style Guide, and improve input handling:
import re
MONEY_REGEX = re.compile(r"[$]?(\d*)(?:\.(\d+))?")
def input_dollars(prompt="", places=3):
"""Input a dollar amount, returned as an integer.
The prompt string, if given, is passed to the input function.
The places argument determines how many decimal places are allowed.
The return value is shifted by that many decimal places,
so that it is an integer.
>>> input_dollars("prompt? ", places=2)
prompt? a
invalid input
prompt?
empty input
prompt? 0.
invalid input
prompt? $32
3200
>>> input_dollars("prompt? ", places=2)
prompt? 32.450
too many decimal places
prompt? 32.4
3240
>>> input_dollars("prompt? ", places=2)
prompt? .6
60
>>> input_dollars("prompt? ", places=4)
prompt? $.472
4720
"""
fix = 10 ** places
while True:
text = input(prompt)
match = MONEY_REGEX.fullmatch(text)
if match is None:
print("invalid input")
continue
integer, fractional = match.groups()
if fractional is None:
if len(integer) == 0:
print("empty input")
continue
return int(integer) * fix
if len(fractional) > places:
print("too many decimal places")
continue
ipart = int(integer) if integer else 0
fpart = int(fractional.ljust(places, '0'))
return ipart * fix + fpart
def format_dollars(dollars, places=3):
fix = 10 ** places
return "${}.{:0>{}}".format(dollars // fix, dollars % fix, places)
def print_final_total(final_total, places=3):
print("Final Total =", format_dollars(final_total, places))
print()
final_total_price = input_dollars("What's the final total price? ")
if final_total_price % 10 in (1, 2, 8, 9):
print_final_total(round(final_total_price, -2))
elif final_total_price % 5 == 0:
print_final_total(final_total_price)
cash_payment = input_dollars("How much cash will you pay with? $")
change = cash_payment - final_total_price
print("Your change is", format_dollars(change))
This code probably doesn't do what you want it to. But, then, neither does your original.

Debugging a simple Python price code

I have this code in Python
def receipt(array):
sum = 0.0
for i in range(len(array)):
sum = sum + array[i]
return sum
array = []
while True:
print("Calculating Price")
n = input("Enter a price: ")
if n == "":
print("Goodbye")
break
array.append(n)
totalCost = receipt(n)
print("The total cost is " + str(totalCost))
And I'm wondering why this code won't work. There seems to be some error in the fourth line
sum = sum + array[i]
But I can't figure out which part of it is wrong. I believe I used the array[i] component correctly. Perhaps it's a string issue?
Question:
Which part of the code doesn't work?
What is my error?
I'm relatively new to computer science in general. Thanks for the help. Anything is appreciated!
I ran your code and got this error:
$ python test.py
Calculating Price
Enter a price: 24
Traceback (most recent call last):
File "test.py", line 14, in <module>
totalCost = receipt(n)
File "test.py", line 4, in receipt
sum = sum + array[i]
TypeError: unsupported operand type(s) for +: 'float' and 'str'
This means that in your sum = sum + array[i] line, the types don't match up. You need to wrap array[i] in a float() function to match array[i] to the type of sum, which is a float since you initialized it to 0.0. The docs say the input() function returns a string, and since you're appending n to array, you are trying to sum a string with a float. The line should look like this:
sum = sum + float(array[i])
Try running it again and the code works. Here is the documentation for input()
Edit: now to fix the issues were were having with the sum.
Here is a version of your code I have revised with corrections to do the addition the way you want.
1 def receipt(sumvar, n):
2 sumvar = sumvar + float(n)
3 return sumvar
4
5 array = []
6 sumvar = 0.0
7
8 while True:
9 print("Calculating Price")
10 n = input("Enter a price: ")
11 if n == "":
12 print("Goodbye")
13 break
14 totalCost = receipt(sumvar, n)
15 sumvar = totalCost
16 print("The total cost is " + str(totalCost))
As mentioned by others, sum isn't a great variable name so I've renamed it sumvar. Notice the sumvar declaration that is outside the function. When you initialize sumvar inside receipt() like you did, you will always be adding n to 0.0. I doubt this is what you want. Instead, you want to keep a running total of the item count, which needs to be passed into the function. I've also eliminated the loop from your function. This loop was actually iterating over the characters in array, not the elements as you expected it to.
First of there are several things wrong. I will explain each and everything.
Here is your complete working code:
def receipt(array):
total = 0.0
for i in array:
total = total + i
return total
array = []
while True:
print("Calculating Price")
n = input("Enter a price: ")
if n=="":
print("Goodbye")
break
array.append(float(n))
totalCost = receipt(array)
print("The total cost is " + str(totalCost))
Your Mistakes:
1)array.append(n) - First one. Pretty common for beginner.
input() in python gets user input as string. So your n is a String.
See there are data types in all languages. And Python is a Strongly typed language while perl is not. How to say if a language is strongly typed or weakly typed ? Simple. Try this in your interpreter.
>>> a=5
>>> b='9'
>>> a+b
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
a+b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
See the error now try this,
>>> a=5
>>> b='9'
>>> a+int(b)
14
Works perfectly fine right. Python doesn't allow just a+b while some languages do example perl. Read more about it. So you can't add them you have to typecast. So change that into
array.append(int(n))
or
array.append(float(n))
If you are going to work with float values.
2) totalCost = receipt(n) See you are passing n to the function. But your function definition has def receipt(array):. What actually happens here is
receipt(n) ----> (calls) ---->def receipt(array):
Where n ------> array So your array is nothing but n. What you should do intead is
totalCost = receipt(array)
3) sum = 0.0 NEVER I said never use built-in or keyword names (ex ample : sum,min,max,int,str etc) as variable names. Read more about naming in PEP 8
So maybe rename sum to sum_ (it's the convention to be followed) However why can't you just rename sum to total much simpler right?
4) And finally
for i in range(len(array)):
sum = sum + array[i]
Why range(len(array)) when you can simply do for i in array:
Can't understand this take a look at this example:
>>> a = [1,2,3]
>>> for i in a:
print(i)
1
2
3
See for item in something would just take each and every item from a group of something ( iterable (list,tuple,set etc..))
So just change those lines to
for i in array:
total = total + i
And voila you got what you wanted,
Output:
Calculating Price
Enter a price: 10
The total cost is 10.0
Calculating Price
Enter a price: 20
The total cost is 30.0
Calculating Price
Enter a price: 15
The total cost is 45.0
Calculating Price
Enter a price:
Goodbye
UPDATE:
As mentioned in comments you need to learn more about indentation. Check out the link in the comments.
You have some problems, I will comment one by one:
First, you had some indentation problems, be careful with that.
The rest are comments in the code
update
def receipt(array):
sum = 0.0
for i in range(len(array)):
sum = sum + array[i]
return sum
array = []
while True:
print("Calculating Price")
n = input("Enter a price: ") #If you convert the str into float here it will cause an error in the if
if n == "": #here, when you hit enter, it sends the "" (empty string)
print("Goodbye")
break
array.append(float(n)) #So an option is transform the string here
totalCost = receipt(array) #and here, you gave to receipt() function the wrong param, you gave "n" and it was waiting for an array
print("The total cost is " + str(totalCost))
You shouldn't use sum as a variable, since it's a built-in in Python, besides, convert your array[i] to a float type when adding it to another float, also notice you never use your initialized array, you are missing that when calculating totalCost:
def receipt(array):
summ = 0.0
for i in range(len(array)):
summ = summ + float(array[i])
return summ
array = []
while True:
print("Calculating Price")
n = input("Enter a price: ")
if n == "":
print("Goodbye")
break
array.append(n)
totalCost = receipt(array)
print("The total cost is " + str(totalCost))
I have corrected what is causing your issue, you are in fact passing in 'n' into receipt instead of 'array'.
def receipt(array):
sum = 0.0
for i in range(len(array)):
sum = sum + array[i]
return sum
array = []
while True:
print('Calculating Price')
n = input("Enter a price: ")
if n == "":
print("Goodbye")
break
array.append(n)
totalCost = receipt(array) #receipt takes a list as a parameter (what you call array)
print("The total cost is " + str(totalCost))
Additional issues are:
indentation (I suspect that was just copy paste)
input will also give you errors the way you are using it, take a look at this to solve that issue
Consider also making your loop based on the value of n as while true is generally unsafe
or at least changing your if statement to be 'not n' as point out here is more pythonic. Also in the future make sure to note the version of python you are using.
Dont use sum as a variable name, it is a Python built-in.
Fixed:
def receipt(array):
total = 0.00 # avoiding 'sum'
for price in array:
total += float(price) # equivalent to 'total = total + float(price)'
return total
array = []
print ("Calculating Price...") # outside 'while' to not reprint each time!
while True:
price = input("Enter a price: ")
if not price: # equivalent to 'if price is False, or 0 in CompSci speak
print ("Goodbye!")
break
array.append(price)
total = receipt(array)
print("The current total cost is", total) # no need to convert to str()
Some words of advice:
When writing a function, its better to be explicit rather than
implicit. So use variables that make sense!
We can use the same variable names because Python uses the LEBG
rule
for variable scope.
When calculating a price (which we know usually ends in 2 decimals)
its better to use integers rather than floats as you will run into
the [problem](
Limiting floats to two decimal points)
with floating point numbers.

Rounding a float that is an str and used in int

I'm trying to replicated a program I made on a Scratch-like application. My problem here is I'm trying to display the user with different numerical data (subtotal, tax and total cost), but when it shows the total cost it gives repeating or terminating decimals. I'd like it to be rounded to two decimals. I've tried adding the round() command inside the program but it's difficult because I'm trying to round a variable rather than an actual number. This is my code so far (line 25 and 28 I believe is where I'm suppose to add a round() or on a new line). I'm very new to Python, I'm using version 3.5.0. I also have searched on here, but the answers were too complex for me. In addition, I got this error: typeerror type str doesn't define __round__ method when adding the round() function in places I assume won't work. Thanks. (ignore after the last else: statement)
#This program asks for the size of pizza and how many toppings the customer would like and calculates the subtotal, tax and total cost of the pizza.
largePizza = 'large'
extraLargePizza = 'extra large'
print ('Answer the follwing question in all lowercase letters.')
print ('Would you like a large or an extra large pizza?')
sizeOfPizza = input()
if sizeOfPizza == largePizza:
print('Large pizza. Good choice!')
else:
print('Extra large pizza. Good choice!')
costOfLargePizza = str(6)
costOfExtraLargePizza = str(10)
oneTopping = 'one'
twoToppings = 'two'
threeToppings = 'three'
fourToppings = 'four'
print ('Answer the following question using words. (one, two, three, four)')
print ('How many toppings would you like on your pizza?')
numberOfToppings = input()
tax = '13%'
if numberOfToppings == oneTopping:
print('One topping, okay.')
if sizeOfPizza == largePizza:
subtotalCostOfLargePizza = str(int(costOfLargePizza) + 1)
**totalCostOfLargePizza = str(int(subtotalCostOfLargePizza) * 1.13)**
print('Your subtotal cost is ' + str(subtotalCostOfLargePizza))
print('Your tax is ' + str(tax))
**print('Your total cost is ' + str(totalCostOfLargePizza))**
else:
print('One topping, okay.')
subtotalCostOfExtraLargePizza = str(int(costOfExtraLargePizza) + 1)
totalCostOfExtraLargePizza = str(int(subtotalCostOfExtraLargePizza) * 1.13)
print('Your subtotal cost is ' + str(subtotalCostOfExtraLargePizza))
print('Your tax is ' + str(tax))
print('Your total cost is ' + str(totalCostOfExtraLargePizza))

Looping certain parts of code within a loop and adding a simplenamespace and a int

import random
import types
attribute = types.SimpleNamespace()
attribute.C1strength= "10"
attribute.C1skill="10"
attribute.C2strength="10"
attribute.C2skill="10"
attribute.counter=""
attribute.counter=1
characterNameOne=str(input("Please input first character's name"))
characterNameTwo=str(input("Please input second character's name"))
print("The characters have 2 attributes : Strength and Skill")
print ("A 12 and 4 sided dice are rolled")
print("Each character is set to 10")
print("The number rolled on the 12 sided dice is divided by the number rolled on the 4 sided dice")
print ("The value of the divided dice is added to the character's attributes")
for counter in range (attribute.counter):
dieOne = random.randint(1,4)
dieTwo = random.randint(1,12)
divisionValue= dieTwo/dieOne
divisionValue= round(divisionValue,0)
x=int(divisionValue)
int(x)
x=(x-0)
print(x)
attribute.C1strength = (attribute.C1strength + str(x))
print(characterNameOne)
print("Your strengh value is :",attribute.C1strength)
attribute.C1strength += str(x)
print("Your skill value is :",attribute.C1skill)
attribute.C1strength += str(x)
print(characterNameTwo)
print("Your strengh value is :",attribute.C2strength)
attribute.C1strength += str(x)
print("Your skill value is :",attribute.C2skill)
fileObj = open("CharacterAttributes.txt","w")
fileObj.write('Charcter one ,your strength:' + str(attribute.C1strength) + '\n')
fileObj.write('Character one, your skill:' + str(attribute.C1skill) + '\n')
fileObj.write('Character two),your strength:' + str(attribute.C2strength) + '\n')
fileObj.write('Characte two), your skill:' + str(attribute.C2skill) + '\n')
fileObj.close()
Hi this is my code ,
I want the character attributes to start at 10 and then the (divisionValue) is then added . The only problem i have is i want the divisionvalue to be added to each charcter's attributes and it adds the digits such as 10 + 1 = would equal 101.
Also , the division value should be different each time so the process should be called each time it is needed . Sorry if my code is wrong , I've just started out on python . Thanks !
In order to concatenate two integers, you would do the following
x = 10
y = 1
z = str(x) + str(y)
Which will give you '101', and if you need to treat that as an int, just do
z = int(str(x) + str(y))
Not quite sure what you mean by the 2nd half of your question.
You may want to wrap your for loop in a function, and pass it thedivisionValue. This will allow you to call it multiple times with different divisionValue values.
This is happening because you are adding string instead of numbers. Just make sure you use integers of the initial strength and skill values and don't apply the str() calls to x when updating those values.

Adding the sum of three digits

So I am writting a program that inputs a 3 # digit and breaks it apart. I am having trouble figuring out how to then add the separate digits altogether?
For example: The user inputs 345
My program will break the #'s apart to 3,4,5 but how do I then add those numbers together?
this is my code thus far,
#set variable
val = raw_input("Type your three digit number please: ")
print 'The first digit is {}'.format(val[0])
print 'The second digit is {}'.format(val[1])
print 'The third digit is {}'.format(val[2])
#set variable
total = [val[0] +val [1] + val[2]]
total_value = total
print 'The sum of the three digits is' total_value
A short way to add all of the number's digits together is:
In [3]: sum(map(int, val))
Out[3]: 12
Here, map(int, val) iterates over the characters of val and converts each of them into an int, and sum(...) adds together all those ints.
The nice thing about this approach is that it works for any number of digits.
The reason your original code doesn't work is that val[0] etc are strings, so using + simply concatenates those strings back together. To add the numeric values, you would have to convert the characters to int first:
In [5]: int(val[0]) + int(val[1]) + int(val[2])
Out[5]: 12
You have to convert the individual components to numbers to be able to add them:
total = int(val[0]) + int(val[1]) + int(val[2])
Or, more concise:
total = sum(int(x) for x in val)
An elegant solution is to use python's builtin functions map and sum:
val = raw_input("Type your three digit number please: ")
total = sum(map(int, val))
print 'The sum of the three digits is', total
You just have to do this :
total = int(val[0]) + int(val[1]) + int(val[2])
Since the digits in val are characters, they have to be converted to integers first.
Note that there are no [ ] around the value affected to total as in your code (you don't want a list, you want a single value).
Try this:
res = raw_input("Enter value: ")
print sum(map(int, res))
i think the answer you looking for is something like this:
a = int(input("3 digit number:"))
x = a // 100
y = a // 10 % 10
z = a % 10
print (x + y + z)
i'm a total noob and its an ez question for noobs learning but when looking for an ez answer i couldn't find it anywhere (here) The question is Adding the sum of "THREE" digits...
I got hung up on if the digits were 5 or 6 long dunno what the code would look like if digits weren't defined.
answer:
a = int(input("enter a few numbers:"))
conversion = str(a)
number =[]
for i in conversion:
a = int(i)
number.append(a)
print (sum(number))
or as shown before me:
number = map(int, str(input('Enter a number: ')))
print(sum(number))
but i still have a ways to goes till i understand this properly

Categories

Resources