-1

I m trying to learn to code in a "pythonic way".

The original code is working, results and displays the expected results. The new code is giving: "<generator object at 0x0000017862039510>". Why then ?

Original code:

a={
    'AA':-5,
    'BB':-8,
    'C':15,
    'D':-85,
    'E':24
}

for i in a.values():
    if i<0:
        print(i)

New code :

a={
    'AA':-5,
    'BB':-8,
    'C':15,
    'D':-85,
    'E':24
}
        
print(i for i in a.values() if i<0 )

Thank you !

Meriole
  • 127
  • 8

3 Answers3

1

i for i in a.values() if i<0 is a generator - it doesn't resolve to a sequence of values unless something iterates it. For parsing reasons, you can't have the generator by itself without enclosing it in grouping parenthesis

>>> i for i in a.values() if i<0
  File "<stdin>", line 1
    i for i in a.values() if i<0
      ^
SyntaxError: invalid syntax
>>> (i for i in a.values() if i<0)
<generator object <genexpr> at 0x7f2a54b3ac80>

print just takes the string representation of objects. It doesn't try to iterate them. So, you get the string representation of the generator itself. Other objects are different - lists and tuples for instance, do iterate their initialization value.

>>> list(i for i in a.values() if i<0)
[-5, -8, -85]
>>> tuple(i for i in a.values() if i<0)
(-5, -8, -85)

List comprehensions do the same thing - build lists using the same generator semantics

>>> [i for i in a.values() if i<0]
[-5, -8, -85]
tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • Thank you so much ! I was exactly looking for this solution with list: ist(i for i in a.values() if i<0) ! – Meriole Oct 08 '21 at 21:08
0

To print out the values of the generator, separated by a newline, you can use .join method which will create a string by joining each element of the generator with a newline (note that the values in the generator must be strings (in this case they need to be explicitly converted)):

print('\n'.join(str(i) for i in a.values() if i < 0))
Matiiss
  • 5,970
  • 2
  • 12
  • 29
  • Or `print(*(i for i in a.values() if i < 0), sep="\n")` – Alan Bagel Oct 08 '21 at 20:58
  • Would a list comprehension also be a good choice? This is what I tend to do since it seems cleaner/simpler: [print(i) for i in a.values() if i<0] – Mandias Oct 08 '21 at 20:58
  • @Mandias there is no point for that, it just creates a list with a bunch of None elements, granted it will also execute the print functions and print `i`, but that is not how list comprehensions are supposed to be used, then just stick to the regular `for loop` – Matiiss Oct 08 '21 at 21:01
  • @Mandias That works, but the list can get unnecessarily large (and thus make it slow) if the number of values is large for a simple operation of printing every item in a list. After printing, python discards a large number of (None) values you didn't need to create in the first place. – Alan Bagel Oct 08 '21 at 21:01
  • @AlanBagel to the first comment: yeah, that is also possible, however, I have a feeling that it is slightly slower; to the second comment: also that list will probably get garbage collected immediately so I wouldn't worry that much about space if using it that way (tho it will temporarily take a lot of it), more of that it just isn't the supposed use and also it would be slower because of multiple `print` – Matiiss Oct 08 '21 at 21:01
  • That makes sense. Thank you for explaining. – Mandias Oct 08 '21 at 21:02
  • Thank you for the response and all the comments, I learned a lot ! – Meriole Oct 08 '21 at 21:09
0

The expression which is written in that print statement of yours is a generator expression. In your original code, you iterate through each key-value pair in your dictionary and print the value. In your new code, you are attempting to print the result of that expression which is an object and not a series of print statements.

Rook
  • 141
  • 13