2017-02-03 8 views
2

어떻게이 흥미로운 (적어도 나에게) 예제를 생각해 냈는가? 하여 콘솔에서 다음자기와 함께 클래스 변수 호출하기

import numpy as np 


class Something(object): 
    a = np.random.randint(low=0, high=10) 

    def do(self): 
     self.a += 1 
     print(self.a) 

if __name__ == '__main__': 
    something = Something() 
    print(something.__str__()) 
    something.do() 
    something2 = Something() 
    print(something2.__str__()) 
    something2.do() 
    something3 = Something() 
    print(something3.__str__()) 
    something3.do() 

위의 지문이 : 나는 (잘못) a의 값이 증가했을 것으로 가정하기 때문에

$ python test.py 
<__main__.Something object at 0x7f03a80e0518> 
1 
<__main__.Something object at 0x7f03a80cfcc0> 
1 
<__main__.Something object at 0x7f03a80cfcf8> 
1 

나는 조금 혼란 스러워요.

@classmethod 데코레이터를 사용하면 예상되는 동작을 얻을 수 있습니다.

import numpy as np 


class Something(object): 
    a = np.random.randint(low=0, high=10) 

    @classmethod 
    def do(cls): 
     cls.a += 1 
     print(cls.a) 

if __name__ == '__main__': 
    something = Something() 
    print(something.__str__()) 
    something.do() 
    something2 = Something() 
    print(something2.__str__()) 
    something2.do() 
    something3 = Something() 
    print(something3.__str__()) 
    something3.do() 

이렇게하면 콘솔에 다음 내용이 올바르게 인쇄됩니다. 내가 self.a 전화있을 때

python test.py 
<__main__.Something object at 0x7faac77becc0> 
3 
<__main__.Something object at 0x7faac77becf8> 
4 
<__main__.Something object at 0x7faac77c3978> 
5 

지금, 나는 내가 무엇을 접근하고있어, 첫 번째 예제에서 궁금하네요? 나는 그것의 가치를 바꿀 수없는 것처럼 보이기 때문에 클래스 변수가 아니다. 이것은 같은 클래스의 다른 객체들 사이에서 공유되는 것처럼 보이기 때문에 인스턴스 변수가 아닙니다. 어떻게 부르죠?

내가 잘못 사용하고있는 클래스 변수입니까? 컨벤션이라면 cls이라는 이름을 알고 있습니다. 클래스 변수에 실제로 액세스하고 있습니다. 그러나 @classmethod 데코레이터를 사용하여 메소드를 꾸미지 않았기 때문에 값을 변경할 수 없습니다.

일종의 비공식적 인 언어 사용입니까? 나중에 버그를 피하기 위해하지 않는 것이 가장 좋습니다.

답변

5

무슨 일이 일어나고있는 것은 self.a두 개의 다른 시간에 가지를 나타냅니다.

이름에 대한 인스턴스 변수가 없으면 Python은 클래스의 값을 검색합니다. 따라서 self.a에 대해 검색된 값은 클래스 변수가됩니다.

그러나 항상 파이썬 것이다 는 인스턴스 변수를 설정, self을 통해 속성을 설정. 이제 self.a은 값이 클래스 변수 + 1과 같은 새 인스턴스 변수입니다.이 속성은 클래스 속성을 쉐도우하며 더 이상 self을 통해 액세스 할 수 없으며 클래스를 통해서만 액세스 할 수 있습니다.

:

0

다니엘 Roseman 의해 답변을 명확하게 문제를 설명합니다. (질문과 아무 상관이 하나의 작은 점, 당신이 대신 something2.__str__()를 호출 직접 이중 밑줄 메소드에 접근해서는 안, 등등 str(something2) 전화) . 여기에 몇 가지 추가 사항이 있으며 도움이되기를 바랍니다. self.a 대신 type (self) .a를 사용할 수 있습니다. 또한 토론을보고 Python: self vs type(self) and the proper use of class variablesPython: self.__class__ vs. type(self)

import numpy as np 


class Something(object): 
    a = np.random.randint(low=0, high=10) 

    def do(self): 
     type(self).a += 1 
     print(type(self).a) 

if __name__ == '__main__': 
    something = Something() 
    print(str(something)) 
    something.do() 
    something2 = Something() 
    print(str(something2)) 
    something2.do() 
    something3 = Something() 
    print(str(something3)) 
    something3.do()