2015-01-28 10 views
5

파이썬 컴파일러에 의해 생성 된 코드 객체는 명령어 (co_consts)에서 사용 된 상수의 튜플과 이름이 포함 된 튜플 (이름이 co_names)을 포함합니다.왜 파이썬 VM은 co_consts를 사용하는 대신 co_names를 사용합니까?

두 개의 별개 목록이있는 이유는 무엇입니까? 이름에도 co_consts을 사용하는 것이 더 간단하지 않습니까?

+0

확인하기 만하면 cpython이 올바른 것입니까? 어떤 버전입니까? –

+0

@GamesBrainiac :'co_names'는 cpython에서 2와 3 모두와 pypy에서 사용됩니다. 다른 구현은 사용하지 않기 때문에 확실하지 않습니다. – 6502

+0

나는 그 모든 것을 잘 기억하지 못한다. 그러나 나는 그것이 산세와 관련이 있다고 확신한다. –

답변

6

다음 기능을 고려하십시오.

def f(x): 
    x += n 
    return x * 4 

여기서 x은 로컬 이름이므로 값이 변경 될 수 있습니다. 4은 상수입니다. 그 가치는 변하지 않을 것입니다. 그러나 여전히 객체이며, 필요할 때마다 새 객체를 만드는 것이 아니라 캐시하는 것이 좋습니다. 마지막으로 n은 글로벌 참조입니다. 문자열 "n"은 함수의 전역 컨텍스트에서 n을 검색하는 키로 사용할 수 있도록 함수에 의해 저장됩니다.

>>> f.__code__.co_nlocals # just 1 (for x) 
1 
>>> f.__code__.co_consts 
(None, 4) 
>>> f.__code__.co_names 
('n',) 
>>> "n" in f.__globals__ and globals() is f.__globals__ 
True 

이름과 const를 별도로 유지하는 이유는 인트로 스펙 션을위한 것입니다. 튜플을 병합 할 수있는 유일한 이유는 메모리 효율성입니다.하지만 함수 당 하나의 객체와 포인터 만 얻을 수 있습니다. 다음 함수를 고려하십시오. consts가 포함 된 튜플은 튜플 포함 된 이름과 병합 된 경우

def g(): 
    return "s" * n 

다음 (안 VM)의 접근 전역에 대한 있었고, 함수의 상수 된 어떤 값 말할 수 없을 것입니다.

1

나는이 대답은 유효 기간이 11개월 비슷하지만 내 땜질에서 보인다 알고있는 사람이 LOAD_GLOBAL (공동 이름 지수)를 사용, 바이트 코드에 co_names에 액세스하려면

일어나고 다음이가에 대한 참조를 밀어 스택에 원하는 co_names는, 예를 들어, 하나 LOAD_CONST (공동 consts 인덱스)

바이트 코드에 co_consts 액세스 간접 사용의 이러한 스택, 즉 직접적인

I에 원하는 co_consts에 저장된 실제 값을 푸시 파이썬 수준에서 직접적인 영향을 미치지는 모르겠지만 바이트 코드 수준에서 보면 차이점

+0

물론 'LOAD_CONST'는 스택 상수를로드하고 LOAD_GLOBAL은 룩업을 대신하므로 큰 차이가 있습니다. 그러나 글로벌 ** 이름 **은 파이썬'str' 객체 일 뿐이며'co_names' 대신에'co_consts'리스트에 넣을 수 있습니다. "LOAD_CONST'를 가지고 있기 때문에'LOAD_GLOBAL' 연산 코드가 필요 없다는 말은하지 않습니다 **. 그러나 두 사람이 두 목록을 갖는 대신에 같은 목록을 사용할 수 있다는 것만 알았습니다. ** 이름 **을 참조하는 opcode는 op_consts를 사용할 수있었습니다. – 6502

+0

그 이유는 모르겠지만 2 강사가 다른 유형의 데이터를 스택에 밀어 넣습니다 (값 대 참조) –

+0

const와 이름이 병합 된 경우 어떤 종류의 지시가 필요합니다. VM이 참조 또는 값인지 여부에 관계없이로드 당 2 개의 명령어 (예 : loadconstname, setconstnametype)이며 단일 호출만큼 빠르지 않습니다. 또한 idjuts (예 : me)가 있으면 바이트 코드가 VM에서 더 안전합니다 원근법 –