Python Forum
penjee . com and non-pythonic code - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: General (https://python-forum.io/forum-1.html)
+--- Forum: News and Discussions (https://python-forum.io/forum-31.html)
+--- Thread: penjee . com and non-pythonic code (/thread-2136.html)

Pages: 1 2


penjee . com and non-pythonic code - buran - Feb-21-2017

Today I saw a post in Facebook showing visualisation from https://panjee.com on separating odd and even numbers from a list. The code goes like this:

numbers = [12, 37, 5, 42, 8, 3]
even = []
odd = []
while len(numbers) > 0:
    number = numbers.pop()
    if (number%2 == 0):
        even.append(number)
    else:
        odd.append(number)
It's really annoying to see non pythonic code propagated by tutoring site. I went to the site just to discover their introductiory video comparing python with other languages that has more of the same (https://youtu.be/r9m__27-R6M?t=40s). I mean the a is 5 and a is True...

I write all this as a word of caution with regards to such resourses...


RE: penjee . com and non-pythonic code - snippsat - Feb-21-2017

There is a lot stuff like this,and even worse when it comes to OOP tutorial for Python here has like over 70% of theme a lot of wrong stuff in them.
As mention in post,also MIT has a lot of wrong stuff in there teaching.


RE: penjee . com and non-pythonic code - nilamo - Feb-28-2017

Aside from just using while numbers, or just using a for loop, what else isn't pythonic about it?

I a little bit don't like if/else used like this, because it isn't obvious at a glance that there's *always* something that happens, every single iteration, so I'd write it like this:

>>> numbers = [12, 37, 5, 42, 8, 3]
>>> separated = {'odd': [], 'even': [] }
>>> for num in numbers:
...   key = 'even' if num % 2 == 0 else 'odd'
...   separated[key].append(num)
...
>>> separated
{'odd': [37, 5, 3], 'even': [12, 42, 8]}
But I don't know if that's any more or less pythonic than just using two different lists.


RE: penjee . com and non-pythonic code - buran - Feb-28-2017

for me for number in numbers loop is the best and most pythonic in this case. while numbers is better than while len(numbers)>0, but still you still need to use pop() (inefficient compared to the for loop - it will make difference if long list, because you change and reindex the list with every iteration). if you HAVE TO, then use collections.deque, especially for long lists.
also I don't like comparison to 0.
key = 'odd' if num % 2 else 'even'
By the way, I don't like ternary conditional operator and use it only in really trivial cases (e.g. in this case it is OK).

numbers = [12, 37, 5, 42, 8, 3]
odd=[]
even=[]
for num in numbers:
    if num % 2:
        odd.append(num)
    else:
        even.append(num)
following is also nice, but maybe not that explicit
from collections import defaultdict
numbers = [12, 37, 5, 42, 8, 3]
separated = defaultdict(list)
for num in numbers:
    separated[num%2].append(num)



RE: penjee . com and non-pythonic code - wavic - Feb-28-2017

In [1]: import numpy as np

In [2]: nums = np.array([12, 37, 5, 42, 8, 3])

In [3]: even, odd = nums[nums % 2 == 0], nums[nums % 2 == 1]

In [4]: print(even, odd)
[12 42  8] [37  5  3]
However I have tried a different apporach but strangely it didn't work. Eight is missing from the even list. And I don't know why. Here I pop() a number and put it to the even list if some condition. So the original list sould contain only odd numbers at the end. Doesn't work  Angry

In [1]: numbers = [12, 37, 5, 42, 8, 3]

In [2]: even = [numbers.pop(numbers.index(n)) for n in numbers if n % 2 == 0]

In [3]: even
Out[3]: [12, 42]



RE: penjee . com and non-pythonic code - buran - Feb-28-2017

in the first example - you iterate twice over the array.
in the second example you change the list over which you iterate in the loop (in this case - in the comprehension) - that's big NO NO
see, it's equivalent to:
numbers = [12, 37, 5, 42, 8, 3]
even = []
print numbers
print 'enter the loop'
for n in numbers:
    print 'index: {}, number: {}'.format(numbers.index(n), n)
    if not n%2:
        numbers.pop(numbers.index(n))
        even.append(n)
    print numbers
print 'exit from the loop'
print even
Output:
[12, 37, 5, 42, 8, 3] enter the loop index: 0, number: 12 [37, 5, 42, 8, 3] index: 1, number: 5 [37, 5, 42, 8, 3] index: 2, number: 42 [37, 5, 8, 3] index: 3, number: 3 [37, 5, 8, 3] exit from the loop [12, 42]
that's why, if use while numbers loop, you always pop the element with index 0, still not good practice because you change the array over which you iterate in the loop


RE: penjee . com and non-pythonic code - wavic - Feb-28-2017

Well, I pop() the current element not the next one. How can run the it step by step and see what is happening?


RE: penjee . com and non-pythonic code - nilamo - Feb-28-2017

Why would you mutate a list your currently iterating over?  

(ants are bugs, yo)
[attachment=129]


RE: penjee . com and non-pythonic code - buran - Feb-28-2017

(Feb-28-2017, 09:38 PM)wavic Wrote: Well, I pop() the current element not the next one.

Note that when you iterate over the list, actually under the hood you iterate over the indexes.

(Feb-28-2017, 09:38 PM)wavic Wrote: Well, I pop() the current element not the next one.
How can run the it step by step and see what is happening?


Look at my code - I expanded the list comprehension for you.
But if you prefer
http://www.pythontutor.com/


RE: penjee . com and non-pythonic code - Ofnuts - Feb-28-2017

Warning: using a comprehension for the side effects should only be attempted by trained professionals.
numbers = [12, 37, 5, 42, 8, 3]
even,odd=[],[]
_=[[even,odd][i%2].append(i) for i in numbers]