There are two answers (1, 2) that include benchmark but for some reason, neither of them include list.index() into their benchmark, even though it was suggested in the accepted answer that was posted at least 2 years before these answers.
list.index() is the fastest option given on this page, including enumerate (all versions that involve it), __getitem__ and numpy.argmin.
Moreover, if the list has a non-unique minimum value and you want to get all indices where the minimum value occurs, list.index in a while-loop outperforms other options such as numpy and enumerate as well. Note that you can limit its search to begin from a particular index by passing the starting point (which is the second argument to list.index), which is crucial for performance because we don't want to search from the beginning in every iteration of the while-loop.
# get the index of the minimum value my_list = [1, 2, 0, 1] idxmin = my_list.index(min(my_list)) print(idxmin) # 2 # get all indices where the min value occurs my_list = [1, 2, 3, 1] idxmins = [] min_val = min(my_list) pos = -1 while True: try: pos = my_list.index(min_val, pos+1) # ^^^^^ <---- pick up where we left off in the previous iteration idxmins.append(pos) except ValueError: break print(idxmins) # [0, 3]
The following benchmarks (performed on Python 3.11.4 and numpy 1.25.2) show that list.index is almost twice as fast as all other options no matter the length of the list. The left graph also shows that getitem performs the same as enumerate (and numpy.argmin) for long lists, which shows that gg349 and Nico's benchmarks are outdated.
The right graph shows that if the minimum value is non-unique and we want to find all indices of the minimum value, then list.index in a while loop as outlined above performs so much better than competing options involving enumerate or numpy, especially for long lists.

The code used to produce the figure above:
from operator import itemgetter import numpy as np import matplotlib.pyplot as plt import perfplot def enumerate_1(a): return min(enumerate(a), key=itemgetter(1))[0] def np_argmin_1(a): return np.argmin(a) def getitem(a): return min(range(len(a)), key=a.__getitem__) def list_index_1(a): return a.index(min(a)) def enumerate_2(a): min_val = min(a) return [i for i, v in enumerate(a) if v == min_val] def np_argmin_2(a): arr = np.array(a) return np.arange(len(a))[arr==arr.min()] def list_index_2(a): result = [] min_val = min(a) pos = -1 while True: try: pos = a.index(min_val, pos+1) result.append(pos) except ValueError: break return result kernels_list = [[enumerate_1, list_index_1, np_argmin_1, getitem], [enumerate_2, list_index_2, np_argmin_2]] n_range = [2**k for k in range(1, 20)] su = lambda n: list(range(n, 0, -1)) titles = ['Get index of a unique min value', 'Get indices of a non-unique min value'] labels = ['enumerate', 'list_index', 'np_argmin', 'getitem'] xlabel = 'List length' fig, axs = plt.subplots(1, 2, figsize=(12, 5), facecolor='white', dpi=60) for ax, ks, t in zip(axs, kernels_list, titles): plt.sca(ax) perfplot.plot(ks, n_range, su, None, labels, xlabel, t, relative_to=1) ax.xaxis.set_tick_params(labelsize=13) plt.setp(axs, ylim=(0, 5), yticks=range(1, 6), xlim=(1, 1100000), xscale='log', xticks=[1, 100, 10000, 1000000]); fig.tight_layout(); fig.savefig('benchmark.png', dpi=60);
divmodexists to prevent having to say[i / 3, i % 3]much.