2011-05-12 2 views
2

내 프로그램에 문제가 있으며 예상치 못한 (최소한 예상치 못한) 동작을 작은 규모로 재현 할 수 있었으므로 다른 버그가 아닌 것으로 확신합니다. .정수 및 목록을 다르게 처리하는 예상치 못한 가져 오기 동작

내가 3 개의 파이썬 모듈을 가지고 있다고하자 : one, twothree. three에서

우리는이 :

var = 0 
list = [] 

을 그래서 거기에 우리가 제로와 빈리스트와 동일한 정수를 가지고있다. two에서

우리는이 :

from three import var, list 

def funct(): 
    print var*2 
    print list 
    return 

그래서 우리는 varlist를 가져 간단하게 모두를 인쇄하고 반환하는 함수를 정의합니다.

funct()two에 전화하는 대신 one에 전화했으나 일부 ​​"작업"을 수행하기 전에는 호출하지 않았습니다.

from three import var, list 
from two import funct 

if 2 < 4: 
    var += 1 
    list.append("x") 

print funct() 

여기 내 질문이 있습니다.

0 
['x'] 
None 
append()으로 목록에 추가 된 방법 x

1 하지이 명확하게하기 위해, var에 추가했다 :

나는이 결과를 기대하지 않았다. 나는 예기하고 있었다 :

2 
['x'] 
None 

동일한 상황의 다른 치료를 받는다는 것이 매우 이상한 경우.

  • 여기에 뭔가가 빠졌습니까?
  • 수입에 문제가 있습니까?

그렇지 않은 경우 :

  • 이 왜 이렇게 행동 하는가?
  • 이 문제를 어떻게 해결해야합니까?

감사합니다.

+2

'list'와 같은 이름을 다시 바인딩하면 안됩니다. 그렇지 않으면 해당 이름으로 내장 객체에 액세스 할 수 없습니다. – bignose

+0

나는 이것을 아래에 답했고, 그것을 스스로 발견하면서 갔다. 나의 대답을 다시 보아라. "three"를 가져와 three.var + = 1을 사용하여이를 발생시켜야합니다. "var"를 가져 오지 마십시오 – malkia

답변

2

은 같이 프로그램, 당신은 "글로벌 VAR"를 추가해야 할 것 "수정"을 세계에 나열된

이름 문은 형식 매개 변수 또는 for 루프 제어 대상, 클래스 정의, 함수 정의 또는 import 문으로 정의되어서는 안됩니다.

다시, 위의 링크 다음

CPython의 구현 세부 사항 : 현재 구현은 후자의 두 가지 제한을 적용하지 않지만, 미래의 구현을 적용 할 수 있으므로 프로그램이 자유를 남용해서는 안 나 자동으로 프로그램의 의미를 변경하십시오.

편집 :

이 솔루션은 변경하는 것입니다 : 다음 글로벌 네임 스페이스를 사용하지 않는

from three import list 
import three 

하지만, (명시 적으로 세 가지의 네임 스페이스를 지정합니다

from three import var, list 

에 기호를 가져 왔습니다.

코드 :

three.var += 1 

확인 two.py 및 one.py 확인은/문

http://docs.python.org/tutorial/modules.html#more-on-modules

에서 자신의 수입에 따라 변경되는 각 모듈은로 사용되는 자체 전용 심볼 테이블을 가지고 모듈에 정의 된 모든 함수에 의한 전역 심볼 테이블. 따라서 모듈 작성자는 사용자의 전역 변수와의 우발적 인 충돌을 걱정하지 않고 모듈의 전역 변수를 사용할 수 있습니다. 다른 한편, 당신이 무엇을하고 있는지 안다면, 함수의 참조를 위해 사용 된 것과 같은 표기법을 사용하여 모듈의 전역 변수를 접할 수 있습니다 : modname.itemname.

+0

흠 감사합니다. 나에게 선택의 여지가 있지만 정말 좋아하지 않는다. 이것은 유일한 직접적인 해결책이다. 어쩌면 나는 완전히 다른 접근 방식을 시도해야한다. ... – Trufa

+0

@Trufa : 다른 모듈에서 객체를 가져 와서 " "메소드를 사용하는 대신에 직접적으로 강타함으로써 그들은 변경할 수 있는지 여부에 상관없이 IMO의 냄새를 맡는다. –

+0

@ JohnMachin : 의견을 보내 주셔서 감사합니다.하지만 대신 수행해야 할 작업을 파악하는 데 문제가 있습니다. – Trufa

-1

이름을 가져 오면 이름에 포함 된 참조가 모듈에 복사됩니다. 코드에서 정수는 리바운드되지만 목록이 변경됩니다. 목록 참조가 변경되지 않으므로 원본 개체가 변경됩니다. 그러므로 다른 정수, 같은 목록.

+0

아니요, 두 경우 모두 가져 오기가 객체에 대한 새 바인딩을 가져옵니다. 수입은 Trufa가 겪고있는 혼란과 아무런 관련이 없습니다. – bignose

+0

하지만 여전히 같은 대상입니다. –

+0

Abrams : 답장을 보내 주셔서 감사합니다.하지만 귀하의 의견을 따르는 데 어려움을 겪고 있습니다. 그리고 저는이 상황을 고려할 때 좀 더 적절한 접근법이 어떻게 생겼는지에 대해 주로 망각하고 있습니다. 감사!! – Trufa

2

이것은 가져 오기와 관련이 없으며 관련된 다른 유형과 관련된 모든 것입니다.

list은 변경 가능한 유형입니다. list.append은 해당 위치에서 개체를 수정하고 None을 반환합니다.

int은 변경 불가능한 유형입니다. 해당 += 연산자는 새 개체를 반환합니다.

Python documentation of its data model에 변경 가능 및 변경 불가능 유형에 대해 자세히 알아보십시오. http://docs.python.org/reference/simple_stmts.html#global에 따라

if 2 < 4: 
    global var 
    var += 1 
    list.append("x") 

그러나 이것은 불법입니다 :

+0

그래, 네가하는 말은 알지만이 방법이 본질적으로 잘못되었거나 두 경우 모두 목록을 사용하여이 문제를 해결해야합니까? – Trufa

+1

해결하려는 문제를 명시 적으로 설명하는 새로운 질문을해야합니다. – bignose

+0

내 질문을 편집하고 더 많은 정보를 추가하겠습니다. 새로운 질문 이라기보다는 전체 코드가 너무 길어 조언을 구하기가 너무 어려워서 많은 가능성을 시도하고 있습니다. – Trufa

관련 문제