Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python loop of strings - why the 'none' comes?

I have a strange question when using python loop. It may be easy but strange to me. Say if I have a list of strings:

seqs=['AA', 'AT']

Then I want to print out elements in the list. One way (method 1) is to use for loop:

for seq in seqs:
    print seq

Which works fine. Meanwhile, I define a 'print' function (method 2) to print:

def print0(s):
    print s

[print0(s) for s in seqs]

If I use the 'print0' function to print out values, this is the output:

AA
AT
[None, None]

I want to know why here comes two 'None' values, since these two values doesn't come when I use the method 1? I want to do the for loop by using paralleling technic, but with the 'None' value, delayed function from joblib package can't work. Thanks. Update: if I want do it parallel:

Parallel(n_jobs=2)(delayed(print0)(seq) for seq in seqs)

It will give an error message:

TypeError: expected string or Unicode object, NoneType found
like image 711
Tian Avatar asked Nov 03 '25 03:11

Tian


2 Answers

Since you are using the interactive interpreter, which by default prints the repr() for any object returned to the top level, you see a list of None objects, which is what got returned from the calls of your print0 function. This is why it's not good practice to create a list just for its side effects, in addition to the fact that all of those objects are stored in memory (although there's only one None object, and that list will be garbage-collected as soon as you return something else to the top level - until then, it's stored in the special variable _).

You'll recognize how the interpreter displays the repr() of any object returned to the top level:

>>> 'hello'
'hello'

And it makes sense that the following literal list is displayed:

>>> [print()]

[None]

And the same for a comprehension:

>>> [print(num) for num in range(3)]
0
1
2
[None, None, None]

But it's better to use an ordinary loop. One-liners are fun, but not always ideal.

>>> for num in range(3):
...     print(num)
...
0
1
2

Note that you can get odd results if a function prints one thing and returns another:

>>> def f():
...     print(1)
...     return 2
...
>>> [f() for num in range(3)]
1
1
1
[2, 2, 2]
>>> for num in range(3):
...     f()
...
1
2
1
2
1
2

This is a demonstration of "side-effects." Try to avoid code that makes changes in two different places at once (in this case, the interactive interpreter's displayed results and the local actions of a function).

like image 88
TigerhawkT3 Avatar answered Nov 05 '25 16:11

TigerhawkT3


The syntax [print0(s) for s in seqs] is a List Comprehension.

It will call print0(s) for every element in seq and put the result into a list. Because print0 returns nothing, you get a list of 2 Nones.

like image 38
byxor Avatar answered Nov 05 '25 16:11

byxor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!