Python Forum
penjee . com and non-pythonic code
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
penjee . com and non-pythonic code
#1
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...
Reply
#2
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.
Reply
#3
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.
Reply
#4
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)
Reply
#5
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]
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#6
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
Reply
#7
Well, I pop() the current element not the next one. How can run the it step by step and see what is happening?
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#8
Why would you mutate a list your currently iterating over?  

(ants are bugs, yo)
   
Reply
#9
(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/
Reply
#10
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]
Unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.
Your one-stop place for all your GIMP needs: gimp-forum.net
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  system programming in pythonic code Skaperen 3 2,921 Jun-21-2018, 01:57 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020