Skip to content

Python specific features

Momtchil Momtchev edited this page Nov 23, 2022 · 6 revisions

Operator overloading

Unlike Python, JavaScript does not support operator overloading. This means that some shortcuts in Python are to be expressed using their method call counterparts. For example a[1] is equivalent to a.__getitem__(1) and a > b is equivalent to a.__gt__(b). For example, to add numpy arrays you can do:

const sum = a.get('__add__').call(b);

Refer to the Python manual for the naming of the Python internal methods used for operator overloading.

Using objects as subscript indices

Knowing how operator overloading works, even the most perverted pandas syntax can be expressed:

// df = pd.DataFrame(np.arange(15).reshape(5, 3), columns=list(['ABC']) })
const df = pd.DataFrame(np.arange(15).reshape(5, 3), {
  columns: PyObject.list(['A', 'B', 'C']),
});
assert.deepEqual(df.columns.tolist().toJS(), ['A', 'B', 'C']);

// df[2:3]
// In Python this is equivalent to df.__getitem__(2:3)
// In pymport item is a shortcut for __getitem__
// Note that if the underlying object also defines an item() function, it will take precedence
// (for example numpy.ndarray.item will be preferred to PyObject.item)
const df2 = df.item(PyObject.slice({start: 2, stop: 3}));
assert.deepEqual(df2.values.tolist().toJS(), [[6, 7, 8]]);

// df[df['C'] <= 3]
// In Python this is equivalent to df.__getitem__(df.__getitem__('C').__le__(3))
const df3 = df.item(df.item('C').__le__(3));
assert.deepEqual(df3.values.tolist().toJS(), [[0, 1, 2]]);

Lvalues

As JavaScript lacks lvalues, assignments of the form

a[i] = x

are not possible. In fact, under the hood, these are also a special case of operator overloading:

a.__setitem__(i, x);

This also works if x is an object.

Slices

Slices can be expressed and used too:

//memoryview(b'123')[::2]
PyObject.memoryview(Buffer.from('123')).item(PyObject.slice({step: 2}))