I have a function with returns a tuple:
def gradiant(params, data):
Q1 = params[0]
Q2 = params[1]
dQ1 = sum(2*(y_i - Q1*x_i - Q2)*(x_i) for x_i, y_i in data)
dQ2 = sum(-2*(y-i - Q1*x_i - Q2) for x_i, y_i in data)
return (dQ1, dQ2)
I'm trying to print the returned values:
grad = gradiant(params, Data)
for x in grad: print(x)
Output:
<generator object <genexpr> at 0x7fdfe009adc0>
<generator object <genexpr> at 0x7fdfe009a5f0>
How do I get to print the integer values?
You have a y-i instead of y_i. It produced a NameError for me. I fixed the typo and it worked fine (I assume, anyway - it printed two numbers).
However, the more interesting issue is how errors are handled within generator expressions (as the typo was part of the generator expression you sent to sum()). I got a NameError, but you got generator expression objects. Look at this function call with an unpacked generator that should contain a TypeError:
>>> print(*(''.join(item2) for item2 in range(3)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print() argument after * must be a sequence, not generator
Now let's see what we get by printing the actual object:
>>> print(''.join(item2) for item2 in range(3))
<generator object <genexpr> at 0x00000000028945E8>
That makes some sense, as generators are lazily evaluated and it was never actually called. But let's see what happens when we send it to list(), which should force evaluation:
>>> print(list(''.join(item2) for item2 in range(3)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
TypeError: can only join an iterable
There's the expected error.
How about a valid generator that contains an invalid generator?
>>> print(*(list(''.join(item2) for item2 in range(3)) for i in range(1)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print() argument after * must be a sequence, not generator
The same uninformative error.
What if we use a list comprehension instead of a generator expression?
>>> print(*[''.join(item2) for item2 in range(3)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
TypeError: can only join an iterable
We get the informative error we were expecting.
Unfortunately, I don't know why this happens, but be extra-careful with generator expressions.
Related
I am stuck on what to do on this problem, tried to execute it on vscode and the hackerrank IDE, both are giving errors even though all solutions on web are same as mine
import math
import os
import random
import re
import sys
#
# Complete the 'plusMinus' function below.
#
# The function accepts INTEGER_ARRAY arr as parameter.
#
def plusMinus(arr):
# Write your code here
neg,pos,zero=0
for i in range(0,len(arr)):
if(arr[i]<0):
neg+=0
elif(arr[i]>0):
pos+=0
else:
zero+=0
print(pos/len(arr))
print(neg/len(arr))
print(zero/len(arr))
return 0
if __name__ == '__main__':
n = int(input().strip())
arr = list(map(int, input().rstrip().split()))
plusMinus(arr)
Traceback (most recent call last):
File "/tmp/submission/20211128/06/29/hackerrank-a7793862d075fcff390bb368bc113c47/code/Solution.py", line 35, in <module>
plusMinus(arr)
File "/tmp/submission/20211128/06/29/hackerrank-a7793862d075fcff390bb368bc113c47/code/Solution.py", line 17, in plusMinus
neg,pos,zero=0
TypeError: cannot unpack non-iterable int object
Reading the traceback reveals the cause of the error you're getting:
Traceback (most recent call last):
File "/tmp/submission/20211128/06/29/hackerrank-a7793862d075fcff390bb368bc113c47/code/Solution.py", line 35, in <module>
plusMinus(arr)
File "/tmp/submission/20211128/06/29/hackerrank-a7793862d075fcff390bb368bc113c47/code/Solution.py", line 17, in plusMinus
neg,pos,zero=0
TypeError: cannot unpack non-iterable int object
The correct syntax would be either
# map the elements of the iterable on the right-hand side to the
# declared variable names
neg, pos, zero = 0, 0, 0
or
# assign the same value to all declared variables
neg = pos = zero = 0
As-written, it's trying to unpack the integer 0 into three separate values neg, pos, zero. Since 0 is not an iterable object like a tuple (as, for example, 0, 0, 0 is), and thus cannot be unpacked into multiple values, python throws an error.
I know what are complex numbers and how they mathematically work, but how is it done for python to know it's complex just by putting a j after a digit ?
>>> j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1*j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1j
1j
>>> 1j**2
(-1+0j)
Can I make my own suffix, let's say p (for strictly positive) ?
Could I do something working like this ?
>>> ... some weird stuff here ...
>>> p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> 1*p
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined
>>> -1p
1p
>>> 0p
1p
>>>
This is built into Python's grammar, just like the decimal point is, or the e in scientific notation (1e10 etc.). The j makes a numeric literal imaginary.
Python does not allow you to change this. That doesn't mean you can't--you could amend the grammar--but then the language is no longer Python.
The closest approximation allowed in Python would be by implementing an operator.
>>> class StrictlyPositive:
def __rmatmul__(self, number):
return abs(number)
>>> p = StrictlyPositive()
>>> -1#p
1
But you have to be careful of operator precedence when doing stuff like this. Why not just use the builtin abs directly?
Why does list(next(iter(())) for _ in range(1)) return an empty list rather than raising StopIteration?
>>> next(iter(()))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> [next(iter(())) for _ in range(1)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> list(next(iter(())) for _ in range(1)) # ?!
[]
The same thing happens with a custom function that explicitly raises StopIteration:
>>> def x():
... raise StopIteration
...
>>> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
StopIteration
>>> [x() for _ in range(1)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
StopIteration
>>> list(x() for _ in range(1)) # ?!
[]
assuming all goes well, the generator comprehension x() for _ in range(1) should raise StopIteration when it is finished iterating over range(1) to indicate that there are no more items to pack into the list.
However because x() raises StopIteration it ends up exiting early meaning this behaviour is a bug in python that is being addressed with PEP 479
In python 3.6 or using from __future__ import generator_stop in python 3.5 when a StopIteration propagates out farther it is converted into a RuntimeError so that list doesn't register it as the end of the comprehension. When this is in effect the error looks like this:
Traceback (most recent call last):
File "/Users/Tadhg/Documents/codes/test.py", line 6, in <genexpr>
stuff = list(x() for _ in range(1))
File "/Users/Tadhg/Documents/codes/test.py", line 4, in x
raise StopIteration
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Tadhg/Documents/codes/test.py", line 6, in <module>
stuff = list(x() for _ in range(1))
RuntimeError: generator raised StopIteration
The StopIteration exception is used to tell the underlying mechanism of the list function when to actually stop iterating on the iterable that has been passed to it. In your case, you're telling Python that the thing that has been passed into list() is a generator. So when the generator throws a StopIteration before generating any items, it outputs an empty list because nothing has been accumulated.
I'm golfing a factorial function in Python 3, but my lambda doesn't work:
f = lambda n:(1,f(n-1)*n)[n>1]
It raises this error:
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
# Many other identical lines...
RuntimeError: maximum recursion depth exceeded
Where's the problem?
Tuples aren't lazily evaluated. Even though f(0) will select the first element in the tuple (1, f(-1)*0), it still has to call f(-1) before it can do so. And before f(-1) can return, it has to call f(-2), and so on forever.
Consider using the inline conditional instead, which does delay evaluation until it knows which branch it's going to go down.
f = lambda n:1 if n <= 1 else f(n-1)*n
print f(10)
While i'm running the following code it shows a TypeError:
a = int(input("Enter the iteration value:"))
b=[]
for c in range[0,a]:
d=int(input("Enter:"))
b.append(d)
f=0
for e in b:
f = f + e
print f
It shows the following error
Enter the iteration value:5
Traceback (most recent call last):
File "/var/app/eclipse/plugins/org.python.pydev_3.5.0.201405201709/pysrc/pydevd.py", line 1845, in <module>
debugger.run(setup['file'], None, None)
File "/var/app/eclipse/plugins/org.python.pydev_3.5.0.201405201709/pysrc/pydevd.py", line 1373, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/opt/odoo/v7.0_cust_mod/Python/print.py", line 68, in <module>
for c in range[0,a]:
TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'
You are using the wrong syntax for the range() function:
for c in range[0,a]:
Note the square brackets, you should use parentheses instead:
for c in range(0, a):
The square brackets are used for subscriptions, which means Python will try and use a __getitem__ method on the range function object. There is no such method, which is why you get your traceback.