UFO ET IT

집합 리터럴은 집합 함수 호출과 다른 결과를 제공합니다.

ufoet 2020. 12. 31. 22:43
반응형

집합 리터럴은 집합 함수 호출과 다른 결과를 제공합니다.


set함수 호출은 중복을 지우지 만 집합 리터럴을 구문 분석하지 않는 이유는 무엇 입니까?

>>> x = Decimal('0')
>>> y = complex(0,0)
>>> set([0, x, y])
{0}
>>> {0, x, y}
{Decimal('0'), 0j}

(Python 2.7.12. 유사한 질문과 동일한 근본 원인 일 수 있음 )


동등성을위한 테스트를 설정하고, 새로운 Python 릴리스가 나올 때까지이 작업을 수행하는 순서는 아래에서 설명하는 것처럼 생성중인 세트에 값을 전달하는 형식에 따라 다를 수 있습니다.

때문에 0 == x사실 0 == y 사실이지만 x == y이고 거짓 , 여기에 행동은 정말 정의되지 않은 세트가 그 가정으로, x == y처음 두 시험이 너무 사실이라면 참이어야합니다.

전달 된 목록 반대로 하면 set()동등성 테스트의 순서가 변경되므로 리터럴을 사용하는 것과 동일한 출력을 얻을 수 있습니다.

>>> set([y, x, 0])
set([0j, Decimal('0')])

리터럴을 뒤집는 경우에도 동일합니다.

>>> {y, x, 0}
set([0])

무슨 일이 일어나고 있는지 집합 리터럴 이 값을 스택에로드 한 다음 스택 값이 새 집합 개체에 역순으로 추가됩니다.

긴만큼 0로드 첫째 , 다른 두 개체가 다음에 대해 테스트 0세트에 이미. 다른 두 개체 중 하나가 먼저로드되는 순간 동등성 테스트가 실패하고 두 개체가 추가됩니다.

>>> {y, 0, x}
set([Decimal('0'), 0j])
>>> {x, 0, y}
set([0j, Decimal('0')])

그 세트 리터럴이 역순으로 요소를 추가하는 것은 Python 2.7.12 및 3.5.2까지 구문을 지원하는 모든 버전의 Python에 존재하는 버그입니다. 최근에 수정되었습니다. 문제 26020 (2.7.13, 3.5.3 및 3.6의 일부, 아직 릴리스 된 항목 없음)을 참조하세요. 당신은 2.7.12을 보면, 당신은 볼 수 있습니다 BUILD_SET에서ceval.c 아래로 위로부터 스택을 읽

# oparg is the number of elements to take from the stack to add
for (; --oparg >= 0;) {
    w = POP();
    if (err == 0)
        err = PySet_Add(x, w);
    Py_DECREF(w);
}

바이트 코드가 역순으로 스택에 요소를 추가하는 동안 ( 0스택을 먼저 푸시 ) :

>>> from dis import dis
>>> dis(compile('{0, x, y}', '', 'eval'))
  2           0 LOAD_CONST               1 (0)
              3 LOAD_GLOBAL              0 (x)
              6 LOAD_GLOBAL              1 (y)
              9 BUILD_SET                3
             12 RETURN_VALUE

수정 사항은 스택에서 요소를 역순으로 읽는 것입니다. 파이썬 2.7.13 버전을 사용하는 PEEK()대신에 POP()(그리고는 STACKADJ()나중에 스택의 요소를 제거하기 위해) :

for (i = oparg; i > 0; i--) {
    w = PEEK(i);
    if (err == 0)
        err = PySet_Add(x, w);
    Py_DECREF(w);
}
STACKADJ(-oparg);

동등성 테스트 문제는 다른 질문과 동일한 근본 원인을 가지고 있습니다. Decimal()클래스는 몇 가지 평등 문제를 가지고있다 complex(하여 파이썬 3.2에서 수정되었습니다 여기 Decimal()에 지원 비교를 complex하고 이전에 지원하지 않은 몇 가지 다른 숫자 유형 ).


세트가 구성되는 순서에 따라 다른 질문 과 함께 발견 한 버그가 결합됩니다 . 리터럴은 목록에서 변환하는 것과 반대 순서로 구성되는 것으로 보입니다.

>>> {0, x, y}
set([0j, Decimal('0')])
>>> {y, x, 0}
set([0])

참조 URL : https://stackoverflow.com/questions/40226063/set-literal-gives-different-result-from-set-function-call

반응형