守着一只汪
修改列表 n-place 不会仅对列表的一部分起作用。您可以改为使用random.sample不替换的随机样本,然后切片分配:k = 10l[:k] = random.sample(l[:k], k=k)print(l)# [1, 7, 6, 0, 2, 3, 4, 9, 8, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
慕慕森
可以使用Fisher-Yates shuffle从根本上重新实现random.shuffle()以接受 afirst和lastindex 作为参数,例如:import randomdef valid_index(i, n): assert(-n <= i < n) return i % ndef shuffle(seq, first=0, last=-1, rand_int_gen=None): n = len(seq) first = valid_index(first, n) last = valid_index(last, n) # use Fisher-Yates shuffle (Durstenfeld method) if callable(rand_int_gen): for i in range(first, last): j = rand_int_gen(i, last) seq[i], seq[j] = seq[j], seq[i] else: getrandbits = random.getrandbits for i in range(first, last + 1): size = last - i + 1 j = getrandbits(size.bit_length()) % size + i seq[i], seq[j] = seq[j], seq[i] return seq像这样使用:l = list(range(20))print(l)# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]random.seed(0) # just to show reproducible resultsshuffle(l, 0, 9)print(l)# [6, 7, 2, 5, 8, 4, 9, 3, 0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]从时间上看,这实际上比random.shuffle()改组整个序列还要快几个百分点。这本质上更快,因为它直接从中获取随机值,random.getrandbits()这是用于随机整数生成的最接近的方法random,其他方法,例如randint()并randrange()最终减少到这个。最后两个最终在内部使用_getrandbelow(),这可能会getrandbits()更频繁地调用必要的。for k in range(1, 7): n = 10 ** k print(n) %timeit l = list(range(n)); random.shuffle(l) %timeit l = list(range(n)); shuffle(l) print() 10100000 loops, best of 3: 6.16 µs per loop100000 loops, best of 3: 3.85 µs per loop10010000 loops, best of 3: 54.3 µs per loop10000 loops, best of 3: 28 µs per loop10001000 loops, best of 3: 585 µs per loop1000 loops, best of 3: 341 µs per loop10000100 loops, best of 3: 6.01 ms per loop100 loops, best of 3: 3.56 ms per loop10000010 loops, best of 3: 71.7 ms per loop10 loops, best of 3: 44.1 ms per loop10000001 loop, best of 3: 815 ms per loop1 loop, best of 3: 582 ms per loop正如@usr2564301 所指出的,这里也建议了这种方法。不幸的是,我认为没有更好的方法可以就地执行此操作。