2016-06-27 4 views
3

클래스 속성을 이해하기 위해 thisthis을 배우고있었습니다. 그러나 다음 코드 스 니펫의 결과와 혼동을 느낍니다.파이썬 클래스의 클래스 속성 음영

class A: 
    aliases = None 
    name = None 

    def __init__(self,name): 
     self.name = name 
     self.aliases = set([name]) 

    def add_aliases(self,a): 
     self.aliases.add(a) 

    def __repr__(self): 
     return str(self.name) + str(self.aliases) 

arr = [] 
for i in range(3): 
    arr.append(A(i)) 
    arr[-1].add_aliases(i+1) 

for item in arr: 
    print item 

A.aliases = set([]) ##Modify the static element of class 
for item in arr: 
    print item 

파이썬 인터프리터 : 2.7.9

그리고 출력은

0set([0, 1]) 
1set([1, 2]) 
2set([2, 3]) 
0set([0, 1]) 
1set([1, 2]) 
2set([2, 3]) 

내가 출력으로 이런 일을 예상하고 있었다.

0set([2, 3]) 
1set([2, 3]) 
2set([2, 3]) 
0set([]) 
1set([]) 
2set([]) 
+0

이 질문은 '코드를 이해하기 쉽도록 클래스 이름별로 클래스 속성을 항상 참조하도록 제안하려고합니다.' – gjha

+0

당신은 내가 원래 게시물에 준 대답을보고 싶을 수도 있습니다. – Shasha99

답변

3

그리고 설명은 우리가 self.aliases = set([])을 쓸 때 우리가 실제로 만드는 클래스 속성 섀도우 인스턴스 속성 있다는 것입니다.

따라서 __init__ 함수를 다음과 같이 만들면 예상되는 결과를 얻게됩니다.

def __init__(self,name): 
    self.name = name 
    A.aliases = set([name]) #using the class attribute directly 

은 또한 코드 다음 사항을 고려 :이 경우, 우리는 하지인스턴스를 만들 속성

class A: 
    aliases = set([]) 
    name = None 

    def __init__(self,name): 
     self.name = name 
     self.aliases.add(name) # using the class attribute indirectly. 

    def add_aliases(self,a): 
     self.aliases.add(a) 

    def __repr__(self): 
     return str(self.name) + str(self.aliases) 

때문에, 어떤 그림자도 없다. 클래스 속성은 모든 인스턴스에서 공유되므로,

0set([0, 1, 2, 3]) 
1set([0, 1, 2, 3]) 
2set([0, 1, 2, 3]) 
0set([]) 
1set([]) 
2set([]) 

예상된다 : 그리고 문제의 테스트 코드는이 출력을 생성한다.

여기서 A.aliasself.aliasinit 또는 다른 기능으로도 참조 될 수 있습니다. 정적 속성을 차단하지 않았으므로 모든 객체가 공통 속성을 공유하는 경우와 같이 예상되는 결과를 제공했습니다.

string 등과 같이 변경 불가능한 데이터 구조를 사용하는 경우이 개념을 모르는 사람은 아무 것도 알지 못합니다. 그러나 listdictionary과 같은 데이터 구조의 경우에는 놀랄 수 있습니다.

init의 정의도 고려하십시오.

def __init__(self,name): 
    self.name = name 
    self.aliases.add(name) # referring to class attribute 
    self.aliases = set([]) # creating a instance attribute 

또한이 경우, 그것은 instance attribute 및 테스트 코드에 의해 생성 된 출력을 생성 결국입니다 :

0set([1]) 
1set([2]) 
2set([3]) 
0set([1]) 
1set([2]) 
2set([3]) 

그리고이 모든 내 학습을 형성하는 것입니다 :

항상 함께 클래스 속성을 참조 클래스 이름과 인스턴스 속성이 객체 이름을 가지고 있습니다. 즉, 클래스 속성이 aliases 인 경우 A.aliases을 쓰고 self.aliases을 쓰지 마십시오. 간접적으로를 참조하십시오.

+0

* "우리가 불변의 데이터 구조를 사용하고 있다면주의를 기울이지 마십시오"* - 정말요? 내 생각에 대부분의 사람들은 자신의 다른 클래스가 예상했던 속성을 공유하지 않는다는 것을 알아 차릴 것이라고 생각한다. – jonrsharpe

+0

@jonrsharpe 잘 링크 된 질문에 그렇게 말했어, 나는 방금 언급 한 두 가지 질문을 보완하기 위해이 질문을 추가했다. – gjha

+0

그렇다면 변경 가능한 클래스 속성과 변경 불가능한 클래스 속성에 대해 다른 질문에서 지적한 점을 잘못 이해했다고 생각합니다. 그것은 그들이 상태 일 때 상태를 공유하지 않고 * 기대하지 않을 때 상태를 공유하는 것과 더 관련이 있습니다. – jonrsharpe

관련 문제