Самый элегантный способ сделать это - random.randrange :
index = random.randrange(len(MY_LIST))
value = MY_LIST[index]
Можно также сделать это в python3, менее элегантно (но все же лучше, чем .index
) с random.choice в диапазоне объект:
index = random.choice(range(len(MY_LIST)))
value = MY_LIST[index]
Единственными допустимыми решениями являются это решение и решения random.randint
.
Те, которые используют list.index
, не только медленны (O(N)
на поиск, чем O(1)
; становится очень плохо, если вы сделаете это для каждого элемента, вам придется делать O(N^2)
сравнений), но ТАКЖЕ у вас будут искаженные / неправильные результаты, если элементы списка не уникальны.
Можно подумать, что это медленно, но оказывается, что оно немного медленнее, чем другое правильное решение random.randint
, и может быть более читабельным. Лично я считаю, что это более элегантно, потому что не нужно возиться с числовым индексом и использовать ненужные параметры, как это имеет отношение к randint(0,len(...)-1)
, но некоторые могут считать это функцией, хотя нужно знать соглашение randint
о включительный диапазон [start, stop]
.
Подтверждение скорости для random.choice: Единственная причина, по которой это работает, состоит в том, что объект range
оптимизирован для индексации. В качестве доказательства вы можете сделать random.choice(range(10**12))
; если он будет перебирать весь список, ваша машина будет замедлена до сканирования.
edit: я пропустил randrange, потому что в документах говорилось "не используйте эту функцию" (но на самом деле означало "эта функция является pythonic, используйте ее"). Спасибо Мартино за указание на это.
Конечно, вы можете абстрагировать это в функцию:
def randomElement(sequence):
index = random.randrange(len(sequence))
return index,sequence[index]
i,value = randomElement(range(10**15)) # try THAT with .index, heh
# (don't, your machine will die)
# use xrange if using python2
# i,value = (268840440712786, 268840440712786)