Str in Python's map and sum - python

Why do you need to use the function 'str' in the following code?
I am trying to count the sum of digits in a number.
My code
for i in number:
sum(map(int, str(i))
where number is the following array
[7,79,9]
I read my code as follows
loop though the array such that
count sum of the integer digits
by getting given digits in a number by map increasingly
such that each object (given number) is converted to String // This does not make sense
Manual says this for str
Type: type
Base Class: <type 'type'>
String Form: <type 'str'>
Namespace: Python builtin
Docstring:
str(object) -> string
Return a nice string representation of the object.
If the argument is a string, the return value is the same object.

Given 79 you need to get [7, 9] in order to sum up this list.
What does it mean to split a number into digits? It means to represent the number in a numerical system with some base (base 10 in this case). E. g. 79 is 7 * 10**1 + 9 * 10**0.
And what is the simplest (well, at least in this context) way to get such a representation of a number? To convert it to a string of decimals!
Your code does exactly that:
>>> str(79)
'79'
# Another way to say this is [int(c) for c in str(79)]
>>> map(int, str(79))
[7, 9]
>>> sum(map(int, str(79)))
16

What happens when you try that code without using str()?
The str() is used to convert the integer into a sequence of characters, so that map() can iterate over the sequence. The key point here is that a "string" can be treated as a "sequence of characters".

Why do you need to use the function 'str' in the following code?
Because map takes an iterable, like a list or a tuple or a string.
The code in question adds upp all the numbers in an integer. And it does it by a little clever hack. It converts the number into a sequence of numbers by doing
map(int, str(i))
This will convert the integer 2009 to the list [2, 0, 0, 9]. The sum() then adds all this integers up, and you get 11.
A less hacky version would be:
>>> number = [7,79,9]
>>> for i in number:
... result = 0
... while i:
... i, n = divmod(i, 10)
... result +=n
... print result
...
7
16
9
But your version is admittedly more clever.

Related

Why is 'int" not iterable in Python, but 'str' are?

I'm getting some practice with list comprehensions and I ran into the following error:
Find all of the numbers from 1-1000 that have a 3 in them
result = [i for i in range(1, 1001) if 3 in i]
print(result)
result = [i for i in range(1, 1000) if 3 in i]
TypeError: argument of type 'int' is not iterable
but it works perfectly if I write this code:
result = [i for i in range(1, 1001) if "3" in str(i)]
print(result)
...So clearly strings are iterable. But ints are not. Why?
Because it’s not clear what iterating over an int would do. You seem to expect that it iterates over the decimal digits (?) but I for example find that unreasonable: I’d find it much more natural to iterate over its bits (i.e. its binary digits). Inside memory, ints are represented as binary numbers, not decimal numbers, so I could argue that mine is the more natural expectation.
But since there’s no obviously right answer, Python’s designers decided not to make int iterable at all.
By contrast, for strings there’s an immediately intuitive “right” answer (although the devil is in the details): we iterate over its characters. Unfortunately that actually opens a can of worms since whole books have been written about the definition of “character”, and in practice something subtly different happens (if you’re curious, start reading The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)). But the answer “we iterate over characters” is close enough.
From a conceptual perspective, the answer by #KonradRudolph is the right one.
But from a technical perspective, what makes an object able to be iterated over? This property is called being iterable. And in Python, an object is iterable as long as it implements the magic method __iter__. Magic methods are special methods Python looks for in a class if it wants to use certain built-in behavior. Like iterating over an object, or adding two objects with +.
And so, we could easily implement our own number class that is iterable:
class IterableInt:
def __init__(self, i):
self.i = i
def __iter__(self):
return map(int, str(self.i))
Here I chose iterable to mean what you expected, i.e. iterating over the decimal digits. Iterating over the binary digits instead would only mean changing one line.
Note that this is not really a number (yet), you cannot add or multiply it. For that one would probably want to inherit from int, but that complicates things a bit more and is left as an exercise.
In any case, now we have an iterable integer:
n = IterableInt(123)
print(3 in n)
# True
print(list(n))
# [1, 2, 3]
If you need to find out if an object is iterable, there are two ways. One is called "Look before you leap" (LBYL), you can test for the existence of the __iter__ method or use the typing module:
hasattr(n, "__iter__")
# True
hasattr(123, "__iter__")
# False
from typing import Iterable
isinstance(n, Iterable)
# True
isinstance(123, Iterable)
# False
And the other is "it’s easier to ask for forgiveness than permission" (EAFP), where you just assume the object is iterable and deal with it if it is not:
try:
3 in 123
except TypeError:
print("too bad, should have used IterableInt")
Because a string is an array of characters. An int is not a sequence of anything (it can be represented as a sequence of digits, but that is not what it is).
if you want to check the int, you have to match with every digit in the int by every tenth place.
from math import floor
def check_if_number_exists(number, digit_to_find):
# check if the number is positive
if number < 0:
Number = -number
else:
Number = number
while(Number != 0):
# run loop for extracting each digit
Digit = Number % 10 # gives the last number
Number = floor(Number / 10) # removing the last digit
if Digit == digit_to_find:
print("the number contains " + str(digit_to_find) + ' in ' + str(number))
break
check_if_number_exists(45638, 3)
you check any number you want with above code.
you cannot do the same way you did for str because int is different from string. A small example
s + e + v + e + n = seven (string is array which comprise of letters)
43567 = 40000 + 3000 + 500 + 60 + 7 (not 4+3+5+6+7)
hope you understand, why iteration dont work on int

I am using `max()` to get the highest value from n digits?

My teacher solved this question "Write a function which takes a n digits number as an input and return True if the biggest digit in this number is divisible by 3" like this:
def is_divisable(n):
a = str(n)
b = 0
for i in a:
if int(i)>b:
b = int(i)
if b % 3 == 0:
return "True"
print is_divisable(67479)
I have thought of it in another way but my code is not working and
I am getting an error says:
"TypeError: 'int' object is not iterable"
def is_dvo(n):
if max(n) % 3 == 0:
return True
print is_dvo(67479)
You don't quite say what your question is, but if you want another way to solve the problem,
def is_divisable(n):
return int(max(str(n))) % 3 == 0
This code converts the number to its decimal string representation, finds the largest digit (as a character), changes that digit to an integer, checks if that is divisible by 3, then returns that answer.
If your question is why you are getting that error, your parameter n is an integer, and you try to apply the max() function to that integer. However, max() is supposed to be used on iterable objects such as strings, lists, tuples, generators, and so on. My code changes the integer to a string before using max() so it does not have that problem, and it iterates over the digits in the string.
You can condense the code to a single line:
def is_divisable(n):
return max(map(int, str(n)))%3 == 0
Try:
max(str(n), key=int) in {'3', '6', '9'}

Functions: changing variable from int to float

I am taking my first python course, this should be an easy thing but I can't get it right. I have done a search, but I guess the keyword are just too common.
So, I did an assignment where I had to write a function that squares a number. I did it successfully with just:
def square(x):
'''x: int or float.'''
return x * x
I have tried with other functions just to try different ways of doing the exercise, if I try to incorporate some loop like:
def square(x):
'''x: int or float.'''
for number in range(x):
result = x * x
return result
It only works for integers(so square(5) gives me 25, but square (5.0) gives me 'TypeError: range() integer end argument expected, got float'. How can I get this function to square floats or negative numbers? Thanks in advance
First question
It's only valid for integers(so square(5) gives me 25, but square (5.0) gives me 'TypeError: range() integer end argument expected, got float'.
Answer
Because range function is defined as taking only integer data. See Python documentation.
Example:
>>> range(5)
[0, 1, 2, 3, 4]
>>> range(5.0)
TypeError: range() integer end argument expected, got float.
>>> range("5")
TypeError: range() integer end argument expected, got str.
>>> range(0, 5)
[0, 1, 2, 3, 4]
>>> range(0, 5.0)
TypeError: range() integer end argument expected, got float.
Second question
How can I get this valid for floats or negative numbers?
Answer
I don't know what "valid" means. It depends on what you are trying to do. So please comment or update your question.
The loop in your second example doesn't actually do anything: it overwrites the value of result every time with the same number, and doesn't even use the loop counter.
If you want an alternate way to compute a square, a method for integers only that uses loops would be this:
def square2(x):
x = int(math.fabs(x))
result = 0
for i in range(x):
result += x
return result
This takes the sum of x added together x times (i.e., converts the multiplication into addition). It handles negative integers as well, but not floats. The reason this doesn't work for floats is that you can't count from 0 to an arbitrary float (real numbers are uncountable).
Honestly, your first solution in your question is the straightforward, simple, and therefore (IMO) the best one.

Adding slicing numbers using a loop

I want to know how can I add these numbers in Python by using a loop? Thanks
num=input("Enter your number: ")
ansAdd= int(str(num)[7])+int(str(num)[5])+int(str(num)[3])+int(str(num)[1])
print....
you want to do it using a loop, here you go:
ansAdd = 0
for x in [7,5,3,1]:
ansAdd += int(str(num)[x])
However, using list comprehension is more pythonic
>>> s = '01234567'
>>> sum(map(int, s[1::2]))
16
Here is how it works:
s[1::2] takes a slice of the string starting at index 1 to the end of the string stepping by 2. For more information on slices see the Strings section of the Python Tutorial.
map takes a function and an iterable (strings are iterable) and applies the function to each item, returning a list of the results. Here we use map to convert each string-digit to an int.
sum takes an iterable and sums it.
If you want to do this without the sum and map builtins, without slices, and with an explicit for-loop:
>>> s = '01234567'
>>> total = 0
>>> for i in range(1, len(s), 2):
... total += int(s[i])
...
>>> total
16
>>> num=input()
12345678
>>> sum(map(int,num[:8][1::2]))
20
here num[:8][1::2] returns only the numbers required for sum(), num[:8] makes sure only the elemnets up to index 7 are used in calculation and [1::2] returns 1,3,5,7
>>> num[:8][1::2]
>>> '2468'
It seems you want to sum odd-numbered digits from user input. To do it with a loop:
num_str = raw_input("Enter your number: ")
ansAdd = 0
for digit in num_str[1::2]:
ansAdd += int(digit)
(The syntax [1::2] is python's string slicing -- three numbers separated by : that indicates start index, stop index and step. An omitted value tells python to grab as much as it can.)
There's a better way to do this without using a traditional loop:
num_str = raw_input("Enter your number: ")
ansAdd = sum(int(digit) for digit in num_str[1::2])
In python 2, input executes the entered text as python code and returns the result, which is why you had to turn the integer back into a string using str.
It is considered a security risk to use input in python 2, since the user of your script can enter any valid python code, and it will be executed, no questions asked. In python 3 raw_input has been renamed to input, and the old input was removed (use eval(input()) instead).

python code explanation reqd

I am new to python, and was going through some pre written code to get a better grip at it.
This code tries to get the number of digits each non-termination cycle has when a number is at the denominator to 1. For eg. 1/3 = 0.(3) it has a cycle of 1.
similary 7 has a cycle of 6 as 1/7 = 0.(142856)
def get_decimals(num, div, current=([], [])):
"""Return a tuple (integer_part, decimal_part, cycle_length) for num/div"""
headtail = lambda lst: (lst[0], lst[1:])
memory, values = current
if values and num == 0:
integer, decimals = headtail(values)
return integer, decimals, 0
elif num in memory:
integer, decimals = headtail(values)
print integer, decimals
lencycle = len(memory) - memory.index(num)
return integer, decimals, lencycle
a, b = divmod(num, div)
return get_decimals(10*b, div, (memory+[num], values+[a]))
print max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
could anyone please explain me in context of the code pasted above. I could not understand the following:
the subscripts [2] and [1] in the last print statement.
memory.index(num) this one inside the get_decimals function at the line 4th to last.
get_decimals(1, num)[2]
get_decimals returns a tuple containing 3 items, named integer, decimals and lencycle. So the subscript [2] picks out lencycle.
max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
The subscript [1] picks out num from a tuple of the form (get_decimals(1, num)[2], num). Note that the max function is applied before the [1] subscript. In this case max is operating on a iterable of tuple pairs and uses lexicographic ordering to compare items.
memory.index(num) calls the method index on the object memory passing num as the parameter. Since memory is a list then this is simply finding the index of the first occurrence of the value num in that list.
Unless you are very new, the above explanation would have made sense. If not, i try explaining in a simpler manner:
for a list a = [1, 2, 3] you would access first element as: a[0]
similarly a subscript of 2 after get_decimals(1, num)[2] means if the function is returning a tuple/dictionary access the third element, in your case the length of the cycle of the non-terminating series. For the input number 7, the output would be 6 as it has a non terminating cycle of 142856.
similarly for line: max((get_decimals(1, num)[2], num) for num in xrange(2, 10))[1]
if you go without the subscript [1] you will see two values printing, but the coder was concerned only with the second value being returned. Apparently the code says:
call the function get_decimals for the values 2 to 10.
Find the max of the tuple being returned and print the second item of the tuple which has been filtered as the max.
Index has been explained pretty clearly and needs no further explanation. Just another simplification:
[1, 2, 3] the index of 2 in list is 1. This will clarify the stuff.
Please refer to the official python documentation, before reading codes. IMHO.

Categories

Resources