2015-02-03 5 views
2

"모든 것이 잘 작동합니다"와 같이 문제가 없다고 말해야하지만 이유를 이해하기 위해 애 쓰고 있습니다.클래스 변수의 이해할 수없는 동작

저는 python/urwid로 스크립트를 작성하고 있습니다. 내 스크립트에는 self._w가 urwid와 같은 클래스 ItemWidget이있다. urwid.Text의 행인 3 개의 위젯의 파일. 게다가, ItemWidget 클래스는 3 개의 boolean의리스트 인 self.visibility와 self.rebuild() 메소드를 가지고있다. 초기화 기능

def __init__ (self, content,vis): 
    self.content = content 
    self.visibility = vis 
    self.rebuild() 
    self.__super.__init__(self._w)  

있어서 재()가 self.visibility의 값에 따라 self._w 재 구축()이다. 사실

for content in abstracts:        # (*) 
    items.append(ItemWidget(content,globalvisibility)) # 

내가 사용 : 스크립트의 main() 함수에서

ItemWidget의 인스턴스 나는 변수

globalvisibility = [1,1,1] 

을하고 난 (약 1000)의 목록을 작성 변수가 아니고

for content in abstracts.items():       
    items.append(ItemWidget(content,[1,1,1]))    

나중에 나는 파일에 globalvisibility를 구현할 것이기 때문에. 하지만이 초기화와 다른 점은 유용하지 않다고 생각했습니다.

어쨌든, 스크립트에서 나는 종종 ItemWidget의 인스턴스를 가지고 예를

에 대한
item.visibility[2] = 0 # (**) 

와 유사한 통해 가시성을 변경합니다. 이 시점까지는 모든 것이 잘 작동하고 예상대로 작동합니다.

여기 내 질문이 있습니다. 왜 (*)를 통해 ItemWidget의 인스턴스를 만든 후에 변수 globalvisibility를 [0,1,1]로 변경하면 이러한 모든 인스턴스에 영향을 줍니까?

실수로 "발견했다"고 말했지만 매우 유용합니다 (나는 ItemWidget의 모든 인스턴스의 가시성 속성을 변경하기 위해 모든 것을 반복해야한다고 생각했지만) - 나에게 - 매우 놀랍습니다. 특히 작업 (**)은 단일 인스턴스에만 영향을 미칩니다.

나는 약간의 설명을 매우 감사 할 것입니다.

편집 : 전체 스크립트는 여기에 있습니다 : https://www.dropbox.com/s/a0a4a0asyi5lyxw/tescik.py?dl=0 예 데이터베이스 itemwidget 경우 내가 인스턴스를 만들 수있는 : https://www.dropbox.com/s/zuwbvggznst85ru/arxiv-2013-05-23.db?dl=0

를 차례로 라인 (58)을 수정하는 당신이 필요로하는 것 그것을 실행하기 위해 데이터베이스 이 동작을 보려면 일부 항목으로 스크롤하고 Enter 키를 누릅니다. 초록은이 항목에서만 사라지고 "초록보기"를 누르면 모든 항목의 동작이 재설정됩니다.

+0

모든 인스턴스가 동일한 목록 개체를 공유하기 때문입니다. –

+1

문제가 어디에 있는지 분명히하기 위해서 :'a = [1,2,3]; b = a; a.append (4); print (b); 또한 놀랍 니? – DSM

+0

@DSM : 이렇게 말하게 해주세요. 특정 인스턴스 (다른 인스턴스가 다른 vis를 가짐)를 통해 (**)를 통해 vis 속성을 변경할 수 있다는 것이 놀랍지 만, globalvisibility를 설정하면 모든 재설정됩니다. 같은 일로 –

답변

2

왜 (*)를 통해 ItemWidget의 인스턴스를 만든 후에 변수 globalvisibility를 [0,1,1]로 변경하면이 모든 인스턴스에 영향을 줍니까?

이러한 모든 인스턴스를 생성 할 때 globalvisibility을 전달했기 때문입니다. 모든 인스턴스는 vis 속성에 동일한 목록에 대한 참조를 저장합니다.

이를 방지하려면 해당 목록을 복사 중 하나 __init__ 방법 또는 인스턴스 생성시 :

def __init__ (self, content,vis): 
    self.content = content 
    self.visibility = vis[:] # here 
    # etc. 

또는를 :

for content in abstracts: 
    items.append(ItemWidget(content, globalvisibility[:])) 

여기 수 있도록 정확한 선택에 따라 달라집니다 당신이 현재의 행동을 원할 지 여부. 그렇다면 __init__()을 그대로두고 인스턴스를 만들 때 사본을 만드십시오.

+0

Thx Kindall, 모든 인스턴스가 vis 속성에서 같은 목록에 대한 참조를 저장한다는 것을 알고 있습니다. 그렇다면 (**)을 통해 특정 인스턴스의 시각을 어떻게 변경할 수 있습니까? 내 화면에 결과가 표시되고 인스턴스가 다른 시각을 갖는 것처럼 보이는 것을 의미합니다. 내가 globalvisibility를 바꿀 때만 그들은 모두 어떻게 든이 공통의 가치로 되돌아 갔다. 어떻게 이런 일이 일어날 수 있겠습니까? –

+0

아니, 할 수 없다. 파이썬에는 당신이 설명했던 것을 처리 할 수있는 아무것도 없습니다. – kindall

+0

킨들, 나는 네가 말하는 것이 사실이라고 믿지만 여전히 이해할 수 없다. 내 대본을보고 싶니? 위의 링크를 게시했습니다. –