: Python


A Python Oddity

The Oddity

Let’s say you want to intialize a matrix (a two-dimensional list) in python. It’ll be an NxN matrix of numbers. Just for fun we’ll make all the inital elements 1, instead of 0.

One might think the following would be a sensible one-liner.

# sample.py
def print_mat(matrix):
    for row in matrix:
        print(row)

matrix = [[1] * 10] * 10
print_mat(matrix)

prints

$ python3 sample.py
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

But, what happens if we modify part of the matrix?

A Small Concurrency Example in Various Languages

The Premise

A common introduction to concurrency is the simple task of spawning two threads, then printing “ping” and “pong” in order N (N = 5 in the following examples) times.

This task is a light intoduction to synchronization primitives like mutexes and condition variables, or in more modern-concurrency models, channels / thread-safe queues.

I figured it’d be interesting to see what this task looks like in different programming languages, so I decided to code it in my four favorite programming languages (python, rust, golang, c++, in that order) to get a sense of their concurrency libraries.

The Curious Case of Dividing Numbers in Python

Positive Numbers

If you’re in the market for converting from python2 to python3, be aware that there’s some fundamental differences in default division of integers. Also beware that these differences won’t be automagically resolved by the tool 2to3.

$ python3
Python 3.8.5 (default, Jul 21 2020, 10:42:08)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 5 / 3
1.6666666666666667
>>>
$ python
Python 2.7.16 (default, Jan 27 2020, 04:46:15)
[GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.37.14)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 5 / 3
1
>>>

As you can see, the / operator in python3 leads to floating point divison by default, which can lead to problems if you’re doing something like calculating memory page indices!