random.shuffle이 None을 반환하는 이유는 무엇입니까?


88

왜 파이썬 으로 random.shuffle돌아 None오나요?

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None

대신 셔플 된 값을 얻으려면 어떻게해야 None합니까?


무작위 값이 아니라 목록의 무작위 셔플 링.
alvas


답변:


157

random.shuffle()x목록 을 제자리에서 변경합니다 .

내부 구조를 변경하는 Python API 메서드는 일반적으로 None수정 된 데이터 구조가 아니라를 반환 합니다.

기존 목록이 순서대로 유지되는 기존 목록을 기반으로 무작위로 셔플 된 목록 을 만들려면 random.sample()입력의 전체 길이와 함께 사용할 수 있습니다 .

x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))     

정렬 키에 sorted()with random.random()를 사용할 수도 있습니다 .

shuffled = sorted(x, key=lambda k: random.random())

그러나 이것은 정렬 (O (NlogN) 작업)을 호출하는 반면, 입력 길이에 대한 샘플링은 O (N) 작업 만 수행합니다 (사용되는 것과 동일한 프로세스 random.shuffle(), 축소되는 풀에서 임의 값 교체).

데모:

>>> import random
>>> x = ['foo', 'bar', 'black', 'sheep']
>>> random.sample(x, len(x))
['bar', 'sheep', 'black', 'foo']
>>> sorted(x, key=lambda k: random.random())
['sheep', 'foo', 'black', 'bar']
>>> x
['foo', 'bar', 'black', 'sheep']

2
임의 값 key함수를 사용하는 것이 진정으로 보장됩니까? 비교가 일관성이 없으면 일부 빠른 정렬 알고리즘이 실패합니다. 구현에 따라 어느 쪽이든 작동하는 것을 볼 수 있습니다 (decorate-sort-undecorate는 key각 요소에 한 번만 적용 하면 잘 정의됩니다).
torek

2
@torek : 파이썬은 콜러 블로 정렬 할 때 decorate-sort-undecorate를 사용합니다 key. 예, 각 값에 정확히 한 번 임의의 키가 제공되므로 보장됩니다.
Martijn Pieters

35

이 방법도 작동합니다.

import random
shuffled = random.sample(original, len(original))

8

문서 에 따르면 :

시퀀스 x를 제자리에 섞습니다. 임의의 인수 인 random은 [0.0, 1.0에서 임의의 부동 소수점을 반환하는 0 인수 함수입니다. 기본적으로 이것은 random () 함수입니다.

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']

6

왜 그래요?

1. 효율성

shuffle목록을 제자리에서 수정합니다. 원본 목록이 더 이상 필요하지 않은 경우 큰 목록을 복사하는 것은 순수한 오버 헤드가되기 때문에 좋습니다.

2. Pythonic 스타일

pythonic style"명시적인 것이 암묵적인 것보다 낫다"라는 원칙에 따르면 , 목록을 반환하는 것은 나쁜 생각 일 것입니다. 왜냐하면 실제로는 그렇지 않지만 새로운 것으로 생각할 수 있기 때문 입니다.

그러나 나는 이것을 좋아하지 않는다!

당신이 경우 않는 새로운 목록이 필요합니다, 당신은 뭔가를 작성해야합니다

new_x = list(x)  # make a copy
random.shuffle(new_x)

멋지게 명시 적입니다. 이 관용구가 자주 필요하면 을 반환 하는 함수 shuffled(참조 sorted)로 감싸십시오 new_x.


2

나는 다음과 같은 개념으로 나의 아하 순간을 보냈습니다.

from random import shuffle
x = ['foo','black','sheep'] #original list
y = list(x) # an independent copy of the original
for i in range(5):
    print shuffle(y) # shuffles the original "in place" prints "None" return
    print x,y #prints original, and shuffled independent copy

>>>
None
['foo', 'black', 'sheep'] ['foo', 'black', 'sheep']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']

파이썬은 기본적으로 참조에 의한 전달 대신 "값에 의한 복사"를 수행하기 때문에 =) stackoverflow.com/a/986495/610569
alvas

2

구조 자체를 변경하는 Python API 는 출력으로 None 을 반환합니다 .

list = [1,2,3,4,5,6,7,8]
print(list)

출력 : [1, 2, 3, 4, 5, 6, 7, 8]

from random import shuffle
print(shuffle(list))

출력 : 없음

from random import sample
print(sample(list, len(list)))

출력 : [7, 3, 2, 4, 5, 6, 1, 8]


0

random.sample()다른 사람의 설명에 따라 셔플 된 목록을 반환 할 수 있습니다 . 그것은 대체하지 않고 목록에서 k 요소를 샘플링하여 작동합니다 . 따라서 목록에 중복 요소가있는 경우 고유하게 처리됩니다.

>>> l = [1,4,5,3,5]
>>> random.sample(l,len(l))
[4, 5, 5, 3, 1]
>>> random.sample(l,len(l)-1)
[4, 1, 5, 3]
>>> random.sample(l,len(l)-1)
[3, 5, 5, 1]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.