DEV Community

Discussion on: 3 Common Mistakes that Python Newbies Make

Collapse
 
kungtotte profile image
Thomas Landin • Edited

One thing you see all the time from people with previous programming experience is trying to make "C-style" for loops iterating over indices and subscripting the list, i.e. for i in range(len(list)) instead of the idiomatic for item in list.

Collapse
 
kungtotte profile image
Thomas Landin

Oh, and generally working against the language and its idioms by shoehorning things into place instead of picking an appropriate data structure or language construct from the outset.

Examples:

Wanting dicts to be ordered instead of using OrderedDict (this is changed in Python 3.7+).

Looping through dicts and accessing elements by key instead of using the appropriate iterator.

Using for loops and indexing to access parts of lists instead of using slices.

Things like that.

Collapse
 
idanarye profile image
Idan Arye

dict ordering is important because keyword arguments are stored in a dict. Consider this:

$ python3.4
Python 3.4.8 (default, Jun 23 2018, 02:35:33) 
[GCC 8.1.1 20180531] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections import OrderedDict
>>> OrderedDict(a=1, b=2, c=3)
OrderedDict([('a', 1), ('c', 3), ('b', 2)])
>>> OrderedDict(c=1, b=2, a=3)
OrderedDict([('a', 3), ('c', 1), ('b', 2)])

We created an OrderedDict, but the constructor was using **kwargs which means the arguments we passed to it were stored in a regular dict and got reordered before OrderedDict.__init__ could store them in order.

With Python 3.6+, the **kwargs stores the arguments in the same order they were written, and the OrderedDict construction works as expected:

$ python3.6
Python 3.6.6 (default, Jun 27 2018, 13:11:40) 
[GCC 8.1.1 20180531] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections import OrderedDict
>>> OrderedDict(a=1, b=2, c=3)
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> OrderedDict(c=1, b=2, a=3)
OrderedDict([('c', 1), ('b', 2), ('a', 3)])
Collapse
 
rhymes profile image
rhymes

A little detail on ordered dicts:

Technically dicts have been ordered since 3.6 on (C)Python, it's just that in 3.7 they decided that to be call "Python 3.7" any implementation has to have the insertion order.

So, dicts in Python 3.6+ are ordered only in the official version, which means that you might have portability issues if you depend on that behavior, but in 3.7+ you are garanteed they will be ordered, regardless of the implementation.

Difference with Python 2:

Python 2.7.15 (default, Jul  3 2018, 10:08:31)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {'b': 1, 'c': 3, 'a': '4'}
>>> a
{'a': '4', 'c': 3, 'b': 1}
>>>

Python 3.6.6 (default, Jul 20 2018, 18:34:07)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {'b': 1, 'c': 3, 'a': '4'}
>>> a
{'b': 1, 'c': 3, 'a': '4'}
Thread Thread
 
kungtotte profile image
Thomas Landin

Yep, that's what I meant by 3.7 being different on that point.

Collapse
 
fabiorosado profile image
Fabio Rosado

I see a lot of this when people want to use the index to do something instead of using for i in enumerate(foo) which returns (index, value)

Collapse
 
kungtotte profile image
Thomas Landin

enumerate is a great tool and it's what you should use when you actually need the index for something, but most of the time people don't really need the index.

And there's a better way to use it:

for index, value in enumerate(foo):
    # voilà, the values are already unpacked
    # into two handy variables!