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.
Related
So I was trying to complete this kata on code wars and I ran across an interesting solution. The kata states:
"Given an array of integers, find the one that appears an odd number of times.
There will always be only one integer that appears an odd number of times."
and one of the solutions for it was:
def find_it(seq):
return [x for x in seq if seq.count(x) % 2][0]
My question is why is there [0] at the end of the statement. I tried playing around with it and putting [1] instead and when testing, it passed some tests but not others with no obvious pattern.
Any explanation will be greatly appreciated.
The first brackets are a list comprehension, the second is indexing the resulting list. It's equivalent to:
def find_it(seq):
thelist = [x for x in seq if seq.count(x) % 2]
return thelist[0]
The code is actually pretty inefficient, because it builds the whole list just to get the first value that passed the test. It could be implemented much more efficiently with next + a generator expression (like a listcomp, but lazy, with the values produced exactly once, and only on demand):
def find_it(seq):
return next(x for x in seq if seq.count(x) % 2)
which would behave the same, with the only difference being that the exception raised if no values passed the test would be IndexError in the original code, and StopIteration in the new code, and it would operate more efficiently by stopping the search the instant a value passed the test.
Really, you should just give up on using the .count method and count all the elements in a single pass, which is truly O(n) (count solutions can't be, because count itself is O(n) and must be called a number of times roughly proportionate to the input size; even if you dedupe it, in the worst case scenario all elements appear twice and you have to call count n / 2 times):
from collections import Counter
def find_it(it):
# Counter(it) counts all items of any iterable, not just sequence,
# in a single pass, and since 3.6, it's insertion order preserving,
# so you can just iterate the items of the result and find the first
# hit cheaply
return next(x for x, cnt in Counter(it).items() if cnt % 2)
That list comprehension yields a sequence of values that occur an odd number of times. The first value of that sequence will occur an odd number of times. Therefore, getting the first value of that sequence (via [0]) gets you a value that occurs an odd number of times.
Happy coding!
That code [x for x in seq if seq.count(x) % 2] return the list which has 1 value appears in input list an odd numbers of times.
So, to make the output as number, not as list, he indicates 0th index, so it returns 0th index of list with one value.
There is a nice another answer here by ShadowRanger, so I won't duplicate it providing partially only another phrasing of the same.
The expression [some_content][0] is not a double list. It is a way to get elements out of the list by using indexing. So the second "list" is a syntax for choosing an element of a list by its index (i.e. the position number in the list which begins in Python with zero and not as sometimes intuitively expected with one. So [0] addresses the first element in the list to the left of [0].
['this', 'is', 'a', 'list'][0] <-- this an index of 'this' in the list
print( ['this', 'is', 'a', 'list'][0] )
will print
this
to the stdout.
The intention of the function you are showing in your question is to return a single value and not a list.
So to get the single value out of the list which is built by the list comprehension the index [0] is used. The index guarantees that the return value result is taken out of the list [result] using [result][0] as
[result][0] == result.
The same function could be also written using a loop as follows:
def find_it(seq):
for x in seq:
if seq.count(x) % 2 != 0:
return x
but using a list comprehension instead of a loop makes it in Python mostly more effective considering speed. That is the reason why it sometimes makes sense to use a list comprehension and then unpack the found value(s) out of the list. It will be in most cases faster than an equivalent loop, but ... not in this special case where it will slow things down as mentioned already by ShadowRanger.
It seems that your tested sequences not always have only one single value which occurs an odd number of times. This will explain why you experience that sometimes the index [1] works where it shouldn't because it was stated that the tested seq will contain one and only one such value.
What you experienced looking at the function in your question is a failed attempt to make it more effective by using a list comprehension instead of a loop. The actual improvement can be achieved but by using a generator expression and another way of counting as shown in the answer by ShadowRanger:
from collections import Counter
def find_it(it):
return next(x for x, cnt in Counter(it).items() if cnt % 2)
The following is a simplified example of my code.
>>> def action(num):
print "Number is", num
>>> items = [1, 3, 6]
>>> for i in [j for j in items if j > 4]:
action(i)
Number is 6
My question is the following: is it bad practice (for reasons such as code clarity) to simply replace the for loop with a comprehension which will still call the action function? That is:
>>> (action(j) for j in items if j > 2)
Number is 6
This shouldn't use a generator or comprehension at all.
def action(num):
print "Number is", num
items = [1, 3, 6]
for j in items:
if j > 4:
action(i)
Generators evaluate lazily. The expression (action(j) for j in items if j > 2) will merely return a generator expression to the caller. Nothing will happen in it unless you explicitly exhaust it. List comprehensions evaluate eagerly, but, in this particular case, you are left with a list with no purpose. Just use a regular loop.
This is bad practice. Firstly, your code fragment does not produce the desired output. You would instead get something like: <generator object <genexpr> at 0x03D826F0>.
Secondly, a list comprehension is for creating sequences, and generators a for creating streams of objects. Typically, they do not have side effects. Your action function is a prime example of a side effect -- it prints its input and returns nothing. Rather, a generator should for each item it generates, take an input and compute some output. eg.
doubled_odds = [x*2 for x in range(10) if x % 2 != 0]
By using a generator you are obfuscating the purpose of your code, which is to mutate global state (printing something), and not to create a stream of objects.
Whereas, just using a for loop makes the code slightly longer (basically just more whitespace), but immediately you can see that the purpose is to apply function to a selection of items (as opposed to creating a new stream/list of items).
for i in items:
if i < 4:
action(i)
Remember that generators are still looping constructs and that the underlying bytecode is more or less the same (if anything, generators are marginally less efficient), and you lose clarity. Generators and list comprehensions are great, but this is not the right situation for them.
While I personally favour Tigerhawk's solution, there might be a middle ground between his and willywonkadailyblah's solution (now deleted).
One of willywonkadailyblah's points was:
Why create a new list instead of just using the old one? You already have the condition to filter out the correct elements, so why put them away in memory and come back for them?
One way to avoid this problem is to use lazy evaluation of the filtering i.e. have the filtering done only when iterating using the for loop by making the filtering part of a generator expression rather than a list comprehension:
for i in (j for j in items if j > 4):
action(i)
Output
Number is 6
In all honesty, I think Tigerhawk's solution is the best for this, though. This is just one possible alternative.
The reason that I proposed this is that it reminds me a lot of LINQ queries in C#, where you define a lazy way to extract, filter and project elements from a sequence in one statement (the LINQ expression) and can then use a separate for each loop with that query to perform some action on each element.
I'm trying to take the values from the previous function and use in another function. This is my first programming class and language, and i'm totally lost.
I figured out how to take the variables from astlist and put them into the function distance, but now Python is telling me I can't use these variables in an equation because they're in a list now? Is that what it's saying?
I'm also just printing the lists to see if they are running. These are two of my functions, and the functions are both defined in my main function.
I'm taking these lists and eventually putting them into files, but I need to figure out why the equation isn't working first. Thanks!
def readast():
astlist = []
for j in range(15):
list1 = []
for i in range(3):
x = random.randint(1,1000)
y = random.randint(1,1000)
z = random.randint(1,1000)
list1.append([x,y,z])
astlist.append(list1)
print(astlist)
return astlist
def distance(astlist):
distlist = []
for row in range(len(astlist)):
x, y, z = astlist[row]
x1 = x**2
y2 = y**2
z2 = z**2
equation = math.sqrt(x+y+z)
distlist.append(equation)
print(distlist)
return distlist
The variable astlist is a list. You're adding list1 to it several times which is also a list. But you're also adding a list to list1 each time: list1.append([x,y,z]). So ultimately astlist is a list containing multiple lists which each contain a list with three integers.
So when you write x,y,z=astlist[row] the variables x, y and z are actually lists, not integers. This means you're trying to compute x**2 but x is a list, not a number. This is why Python is giving you an error message as ** doesn't support raising a list to a power.
I'm not sure what you're trying to accomplish with all these lists but you should change the code so that you're only trying to raise numbers to the power of two and not lists.
There are a few problems here:
Firstly the loop at the top of readast() sets list1 to [] 15 times - I'm not sure what you're trying to do here. If you are trying to generate 15 sets of x,y,z coordinates then it is the second range - in your example the range(3)
- that you need to change.
Then you keep adding lists of [x,y,z] to (the same) list1, then adding the whole of list1 to astlist. However, Python actually stores a pointer to the list rather than a copy so when you add items to list1, it adds items to list1 whereever list1 is included in another list:
In this example the random numbers are replaced with sequential numbers for clarity (the first random number is 1, the second 2 and so on):
After first cycle of loop:
list1: [[1,2,3]]
astlist: [[[1,2,3]]]
After second cycle of loop:
list1: [[1,2,3],[4,5,6]]
astlist: [[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]]
and so on
As you can see, list1 is now a list of lists, and astlist is now a list of duplicates of list1 (a list of lists of lists)
list1 is probably redundant and you probably want just
astlist.append([x,y,z])
in the first bit.
In the second function, you use
for row in range(len(astlist)):
x,y,z=astlist[row]
...
but actually the following would be better:
for row in astlist:
x,y,z=row
...
or even:
for x,y,z in astlist:
...
as for loops in Python iterate over members of a sequence (or other iterable value) rather being just a simple counter. What you are doing with the range(len(astlist)) construct is actually generating a list [1,2,3...] and iterating over that.
If you particularly need a numerical index then you can use the enumerate function which returns a series of (index,value) pairs that you can iterate over thus:
for i,value in enumerate(['apple','banana','cherry']):
print 'value {} is {}'.format(i,value)
value 0 is apple
value 1 is ball
value 2 is cherry
Hope this helps
I will refer to the specific type error (TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'), for some reason arrays are iterable objects for operations like addition: sum(array), but, power: array**2, pow(array,2). You can solve this with some extra steps as follow:
x1 = [j**2 for j in x]
also I recommend to use sum function
sum(x,y,z)
remember all this is to avoid the error message that you were referring to
that way you apply the power of 2 to each element in the array, getting a new array and avoiding the error message that you were asking help for. It seems to me that you are looking to get a normalization of your data using norm L2, if that is true, well, I think you are missing half of it.
Problem number 10 of Project Euler asks us to calculate the sum of all primes below 2,000,000.
My algorithm for the same is:
Construct a sieve for numbers under 2,000,000
Sum all the numbers in the sieve.
I am not comfortable with the code creating multiple lists instead of performing computations over the same list.
Given below is my code:
def main(number_above):
list_of_numbers = list(range(number_above))
list_of_numbers = calculate_sieve(list_of_numbers)
print summation_of_primes(list_of_numbers)
def calculate_sieve(list_of_numbers):
for prime in list_of_numbers:
if prime >= 2 and prime != 'C':
multiple = 2
while multiple * prime < len(list_of_numbers):
list_of_numbers[ prime * multiple ] = 'C'
multiple += 1
return list_of_numbers
def summation_of_primes(list_of_numbers):
summation = 0
for element in list_of_numbers:
if element != 'C':
summation += element
return summation - 1
The steps in which the lists are created:
First, a list is created of numbers in range(2,000,000)
Second, this list is passed on to the calculate_sieve function which cancels all composites.
Then, the calculate_sieve function returns a list to the main function.
Finally, this list is passed on to the summation function.
Is python operating on the same list in place, or does it hold more than one list at a time?
If it is creating multiple copies of the list, is there a way to minimize memory usage by operating on the list in place?
Is python operating on the same list in place?
Yes, mostly.
passing a list as an argument to a function does not create a new list.
modifying elements in a list does not create a new list.
returning a list from a function does not create a new list.
The only code you have that may potentially create a duplicate list is this line:
list_of_numbers = list(range(number_above))
In Python 2.7 and below, range already returns a list. Calling list on the result will create a second list. You can safely just write list_of_numbers = range(number_above) and save yourself a little memory.
In 3.X, range returns a range object, so the list call is necessary there, if you want to subsequently do assignment, like list_of_numbers[ prime * multiple ] = 'C'.
You can check it very easily:
In [1]: def some_func(seq):
...: seq.append(1)
...:
In [2]: s = []
In [3]: some_func(s)
In [4]: s
Out[4]: [1]
Since s got modified some_func cannot operate on a copy of it.
Identifiers (or variables) in python are always references to an object. They are not memory locations. They are names to an object. When you pass an object to a function the arguments simply creates a new reference to that object, so there's no copying involved.
I believe all your computations are performed on the same list in place, a list is mutable and it is passed by reference, hence I believe in your case there will only be one list in memory at the same time.
print max(3 for i in range(4))
#output is 3
Using Python 2.6
The 3 is throwing me off, heres my attempt at explaining whats going on.
for i in range(4) makes a loop that loops 4 times, incrementing i from 0 to 3 at the start of each loop. [no idea what the 3 means in this context...] max() returns the biggest iterable passed to it and the result is printed to screen.
3 for i in range(4) is a generator that yields 3 four times in a row and max takes an iterable and returns the element with the highest value, which is, obviously, three here.
This evaluates to:
print max([3,3,3,3])
... which is an elaborate way to say print 3.
expr for x in xs is a generator expression. Typically, you would use x in expr. For example:
[2*i for i in range(4)] #=> [0, 2, 4, 6]
It can be rewritten as:
nums = []
for i in range(4):
nums.append(3)
print max(nums) # 3! Hurrah!
I hope that makes its pointlessness more obvious.
The expression:
print max(3 for i in range(4))
is printing the result of the max() function, applied to what is inside the parentheses. Inside the parentheses however, you have a generator expression creating something similar to an array, with all elements equal to 3, but in a more efficient way than the expression:
print max([3 for i in range(4)])
which will create an array of 3s and destroy it after it is no longer needed.
Basically: because inside the parentheses you will create only values that are equal, and the max() function returns the biggest one, you do not need to create more than one element. Because with the number of elements always equal to one, the max() function becomes not needed and your code can be effectively replaced (at least in the case you have given) by the following code:
print 3
That is simply all ;)
To read more about differences between comprehension and generator expression, you can visit this documentation page.