errors = int(0)
for i in range(len(expectedData)):
if data[i] != expectedData[i]:
errors += int(binary_compare(data[i], expectedData[i]))
return errors
I have the above code which I am trying to use to calculate some integer (number of errors) for some data. I have casted everything I can see possible as an integer, yet the line "errors += ..." still appends the value, rather than adds it.
For example, if my answer should be 7, I might get 500002. (5 + 0 + 0 + .. + 2). I have never run into this before. The function binary_compare is returning an integer as well, but I'm completely in the dark as to why this isn't working.
python is not javascript
it's no way to get concatenated strings instead of math sum, when you do count += value starting with count = 0. if you try to add a string to integer, exception is raised:
>>> x = 0
>>> x += "1"
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
to compare values of which you don't know whether they are strings or integers, i'd use
str(data[i]).strip() == str(expectedData[i]).strip()
for noninteger-proof math sum, you might want to do something like this
try:
value = int(expectedData[i])
except:
value = 0
count += value
I think the error is outside of your code, but anyway, in Python, list operations are seldom done with loops, as this focuses on the implementation rather on the purpose. List comprehension, generators etc are preferred, and there are also many built-in and standard library functions for common tasks.
In your case, I would write the function as
return sum(binary_compare(x, y) for x, y in zip(data, expectedData) if x != y)
If you are using Python 2.x, itertools.izip should be used instead of zip.
Related
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 trying to grasp what mechanism is keeping track of values being returned to the sum() function in the following:
def narcissisticNumber(value):
return value == sum(int(x) ** len(str(value)) for x in str(value))
From what I see, x ** y is being calculated for each character in the value string - however, since the 'for char in str' construct is within the sum function, the result of each of these computations is being returned to sum(). The return value of sum() accounts for all iterations, and I would like to know how sum() was able to track all the return values of the x ** y expression.
I am using Python 3.7.4. Coming from Java, I understand the function does not follow best practices, I would just like to know how it works in terms of Python.
What you are using is a Generator:
Generators are a simple and powerful tool for creating iterators. They
are written like regular functions but use the yield statement
whenever they want to return data. Each time next() is called, the
generator resumes where it left-off (it remembers all the data values
and which statement was last executed)
Check here for better understanding: https://wiki.python.org/moin/Generators
I think a good way of understanding it better would be to break it down to a more readable format:
def narcissisticNumber(value):
listOfValues = []
lenOfValue = len(str(value))
# Iterate through each character in your string
for x in str(value):
# Get the int-value of that character
# then raise it to the length of your string
xRaiseToLength = int(x) ** lenOfValue
# Append that value to your final list
listOfValues.append(xRaiseToLength)
# Compute the sum of the list using sum()
sumOfValues = sum(listOfValues)
return value == sumOfValues
References:
sum()
Okey lets break it into parts:
str(value) is casting value into a string (str)
len(str(value)) is getting the length of this string
... for x in str(value) is a generator expression. It will assign to x each element in str(value) (this is, each character) and evaluate the first clause. To simplify this, you can think that it returns an array. It actually doesn't, but conceptually yopu can think of it like that. It is actually creating a special construct that can be iterated over and that evaluates each element when they are requested, so it is way more memory efficent that creating an array.
int(x) is casting x (which is each of the characters of the string) into an integer (int).
int(x) ** len(str(value)) is calculating x to the power of the length of the complete string.
sum is a fucntion that accepts any iterable construct (in this case a generator, but it could be an array of some sort) and adds its elements.
So in conclussion, if you do narcissisticNumber(123) it will return 1^3 + 2^3 + 3^3 = 1 + 8 + 27 = 36.
I'm trying to get the minimum odd number using python. I used lambda, loops and other methods to get minimum odd number but i was not able to get that using functions. here is my code
z= [1,8,-4,-9]
def min_odd(x):
for i in x:
if (i%2!=0):
return min(i)
y = min_odd(z)
print (y)
Can some please tell me what i was missing here.
The min() function expects an iterable like a list which it will then yield the smallest element from.
E.g. min([1,0,3]) gives 0.
So if you want to use it, you must create a list (or other iterable) of the odd numbers that you can then pass into it:
def min_odd(x):
odds = []
for i in x:
if i % 2 != 0:
odds.append(i)
return min(odds)
note that we could also use a list-comprehension:
def min_odd(x):
return min([i for i in x if i % 2 != 0])
which both work.
An alternative method would be to store the current minimum odd value in a variable and update this variable if we come across a smaller odd value:
def min_odd(x):
min_v = float('inf')
for i in x:
if i % 2 != 0 and i < min_v:
min_v = i
return min_v
Try:
min([val for val in z if val % 2 != 0])
It seems your code logics are wrong. First off, you seem to have an indentation error in the return statement. Second off, the min() function requires a collection of items (like an array for example) or a series of arguments to determine the minimum in that series. You can try multiple things.
Use another variable to store a temporary minimum. Replace it every time you find a smaller odd value ( for every i in x... if the value is odd and is smaller than the previous odd value, replace it) and have it started with the first odd number you can find.
Take all the odd numbers and add them to another array on which you will apply the min function.
Hope this proves useful!
You could pass a generator into the min() function:
def min_odd(iterable):
return min(i for i in iterable if i % 2)
I didn't write i % 2 != 0 because any odd number will return 1 which has a Boolean value of True.
I added a parameter to the function that takes the iterable so it can be used for any iterable passed in.
min operates on an iterable. i is not an iterable in your code; it's the last element of the list.
You can achieve what you want with a filter, though:
min(filter(lambda e: e%2 != 0, x))
I have a weird Python beginner's question,.. playing around in my virtual env in the interpreter (python 3.5):
I have a list with mixed types:
lissi = ["foo", "bar". "boo", "baz", 4, 7]
And then "accidentally" try to print out all elements in a for loop concatenated to a string:
for x in lissi:
print("Hallo " + x)
This, of course, is not possible bcs. we cannot conc. integers to a String - so the first elements are printed and then there is a TypeError.
Then I typed just "x" and enter to see if there is still data stored and yes it is: x is 4.
type(x) is int (tried that to figure out if 7 is also still there).
So my question is: What happens "under the hood" in Python in the for loop: Seems as if every successfully processed element is removed, but there is a backlog stored in x which is the first element the TypeError was thrown for? And is there a way to "clear" this data from memory in case of errors?
thx
The for loop is part of the scope it is declared in, so the following code will change the value of x:
x = 9
for x in xrange(3): # iterate 0, 1, 2
print(x)
print(x) # x == 2, x != 9
When the element was "baz", everything was okay and the print statement worked. Python then continued execution. The next step was x = 4. After that, print "Hallo" + x failed with an error.
While running the interpreter, errors are caught and printed, then execution continues. There is no cleanup after an error in the interpreter, so the last value of x is still there when you check the value. This is why you see 4.
It's not a backlog and nothing like "every successfully processed element is removed".
Basically on every iteration for loop assigns to variable x the value of next element of list lissi (doesn't have to be a list, can be any iterable).
Whenever the loop breaks, due to exception or break statement, variable x is left intact, so it contains the last value assigned by the for loop.
This is ok, since loops don't have any isolated scope in Python and actually makes it convenient to search iterable for interesting element, breaking the loop when it's found and not being forced to store it in another variable before leaving the loop.
I believe the problem is not with the for loop, but with the print() statement.
You cannot + a string with an integer, example:
This will not work:
print("Hallo " + 4)
nor will this:
print(4 + " Hallo")
if it is all integers it will work:
print(4 + 1)
the error which is shown from print("Hallo " + 4) is "builtins.TypeError: Can't convert 'int' object to str implicitly"
The solution is to do the conversion from integer to string explicitely:
for x in lissi:
print("Hallo " + str(x))
Now, for your question, I do not believe there is something as a "back log". The enumeration of for x in lissi is still valid, and x is still valid, just that while processing the first 4 enumerations (where x is a string) the print() statement will work, then it throws an error on the print() statement, but x is still a valid integer.
I am trying to evaluate power series using python. series => e^x = 1+ x+ x^2/2! + x^3/3!...x^n/n!
I am getting this error ''int' object has no attribute 'extend'.
My code:
import math
print('give x')
x = float(input())
n =100
k = 0
list = (1)
while 0<x<1:
list.extend([math.pow(x,K+1))])
k = k+1
if x==n:
break
print(sum(list))
Please help!
There are multiple problems with your code.
Firstly, you are attempting to create a list with (1) - that just creates the integer object 1, the parentheses have no effect here. To create a list containing 1 you need [1]. And you shouldn't use the names of Python built-ins (like list) as variable names - not only is it confusing to other people who may read your code it makes the built-in inaccessible, which can lead to mysterious bugs.
K is not the same as k.
Your while 0<x<1: test does't make much sense; FWIW, the Taylor series for ex converges for all values of x.
Your if x==n: test should be if k==n:, although it'd be better to use a for loop with range (or maybe xrange in Python 2).
You don't need to save the terms in a list - just add them as you go.
You don't need math.pow - x**k calculates the same thing as math.pow(x, k), but even that's unnecessary here: you should just keep track of the previous term and multiply it by x on each loop.
You forgot the /n!. Once again, you don't really need to compute the factorial (or call the math.factorial function) since you can just divide the previous term by k.
Hopefully, that's given you enough clues to fix your code. I won't provide working code at this stage, since I suspect this is a homework problem. Note that the math module has an exp function which you can use to test the accuracy of your power series calculations.
A list literal is created with square brackets, []. You can use parentheses, (), for grouping or for creating a tuple. In the case of list = (1), they are being used for grouping, so this is the same as list = 1. (A tuple with one element is created with mytuple = (1,) or just mytuple = 1,.)
At this point, I'll mention that naming one of your variables list masks the built-in function list, so after you do that you can't access that function anymore without some effort. It's best to name your object something else, like lst.
A list's extend() method adds all the elements from the passed list onto the object you're accessing, so if mylist was [1, 2, 3], mylist.extend([4, 5]) would result in mylist becoming [1, 2, 3, 4, 5]. However, you only have one object to add, so it makes more sense to use append(), which adds the passed object to the given list.
x = float(input('Give x: ')) # the input function can be passed a prompt string
n = 100
k = 0
lst = [1] # changed name, created a list
while 0<x<1:
list.append(x**(k+1)) # you can just use the ** operator if you want
# also, k isn't K
k = k+1
if x==n: # x is never changed, so your loop either never runs
# or goes forever
break
print(sum(lst))
Note the while loop that will either never be entered or never finish. You'll have to take another look at your program's logic.