2017-02-06 1 views
3

나는 다음과 같은 코드에 대한 몇 가지 약간 예기치 않은 동작이 점점 오전 :파이썬 클래스 변수와 인스턴스 변수 혼란

class MyClass(object): 
    value = 5 

object1 = MyClass() 
object2 = MyClass() 

print object1.value #This displays 5 
print object2.value #This displays 5 
print MyClass.value #This displays 5 

#So far so good 

object1.value = 6 

print object1.value #This displays 6 
print object2.value #This displays 5 
print MyClass.value #This displays 5 

#Still good, but the confusing part is coming up... 

MyClass.value = 10 

print object1.value #This displays 6. I was expecting it to be 10! 
print object2.value #This displays 10 
print MyClass.value #This displays 10 

당신이, 내가 변수의 경우 버전을 변경하고 확인하고 예상 결과를 얻을 수있다. 그러나 MyClass.Value를 10으로 변경하면 모든 인스턴스의 값이 변경 될 것으로 예상됩니다. 그러나 아마도 내 이해가 정확하지 않을 수 있습니다.

모든 도움을 주시면 감사하겠습니다.

답변

1

처음에는 object1object2이 모두 인스턴스 별 변수없이 MyClass의 인스턴스입니다. 그런 다음 object1.value을 변경합니다. 아직 MyClass의 회원이지만, object1.value을 요청하면 MyClass의 값이 보지 못했기 때문에 6을 얻습니다. 지금까지 예상되는 동작을 제공합니다.

MyClass.value을 10으로 변경하면 MyClass.value을 조회 할 때마다 10이됩니다. 직접 조회하거나 object2을 통해 조회 할 때 발생합니다. 그러나 object1은 여전히 ​​0으로 설정되어 있으므로 value이 있습니다. 따라서 object1.value을 묻는 경우 object1에서 value을 조회하고 6을 봅니다. MyClass의 버전이 변경된 것을 알 수 없습니다.

object2에 대해서는 value이 없기 때문에 발생하지 않습니다. 조회가 object2에서 실패하므로 object2.__class__.value을 찾으려고합니다. object2MyClass의 인스턴스이기 때문에, object2.__class__MyClass, 당신은 다음 방금 object2와 마찬가지로, MyClass에서 10를 얻을 것, object1.value를 조회, del object1.value 말한다면 그것은 10

을 제공합니다. 후드 아래에 어떻게됩니까

0

은 당신이 예를 속성을 할당 할 때, 해당 인스턴스의 개인 사전 (__dict__)가 업데이트 될 때,이다,하지만 클래스의 __dict__. 전자는 요청 된 속성의 검색에 우선 순위를 가지며, 처음 몇 줄에서는 항상 object2에 대해 찾을 수없는 경우 클래스의 __dict__을 사용하여 속성을 찾습니다. 특히

:

속성 할당 및 삭제 인스턴스의 사전, 결코 클래스의 사전을 업데이트합니다. 클래스에 __setattr__() 또는 __delattr__() 메서드가있는 경우이 메서드는 인스턴스 사전을 직접 업데이트하는 대신 호출됩니다. .

(강조 광산 the Python documentation on the standard type hierarchy in the data model에서, 당신은 서브 섹션 "클래스 인스턴스", 두 번째 단락을 찾아야합니다 단락을이 인스턴스와 거래하기 전에 속성 조회 순서를 전체 하위 섹션과 하나 전합니다.. , "사용자 정의 클래스"는 컨셉을 얻기 위해 읽는 것이 좋을 수 있으며, 아마도 다소 응축되기 때문에 몇 번이나 읽을 수 있습니다.)는 종종 저 아래에 무슨 일이 일어나고 있는지 이해하는 데 도움이 무엇


, 클래스,이 경우 ID와() 관련 인스턴스의 __dict__ 속성을 인쇄하는 것입니다 및 속성. 이 id는 당신이 같은 객체를보고 있다는 것을 보장하지 않지만 CPython을 사용할 때 일반적으로 나를 위해 일해 왔습니다.

당신이 인쇄 조정 코드 :

from __future__ import print_function 

class MyClass(object): 
    value = 5 

object1 = MyClass() 
object2 = MyClass() 

print(object1.value, id(object1.value), object1.__dict__) 
print(object2.value, id(object2.value), object2.__dict__) 
print(MyClass.value, id(MyClass.value), MyClass.__dict__) 

object1.value = 6 
print(object1.value, id(object1.value), object1.__dict__) 
print(object2.value, id(object2.value), object2.__dict__) 
print(MyClass.value, id(MyClass.value), MyClass.__dict__) 

MyClass.value = 10 
print(object1.value, id(object1.value), object1.__dict__) 
print(object2.value, id(object2.value), object2.__dict__) 
print(MyClass.value, id(MyClass.value), MyClass.__dict__) 

과 (편안함을 읽기 위해 삽입 된 몇 가지 여분의 줄 바꿈과 공백) 내가 얻을 출력 :

5 4325640816 {} 
5 4325640816 {} 
5 4325640816 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 
    '__dict__': <attribute '__dict__' of 'MyClass' objects>, 
    '__module__': '__main__', 'value': 5} 

6 4325640848 {'value': 6} 
5 4325640816 {} 
5 4325640816 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 
    '__dict__': <attribute '__dict__' of 'MyClass' objects>, 
    '__module__': '__main__', 'value': 5} 

6 4325640848 {'value': 6} 
10 4325640976 {} 
10 4325640976 {'__doc__': None, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 
    '__dict__': <attribute '__dict__' of 'MyClass' objects>, 
    '__module__': '__main__', 'value': 10} 

ID입니다은별로 달라집니다 실행 및 시스템과 편리하게 여기서 'value'은 항상 MyClass.__dict__에 마지막으로 인쇄되지만 어떤 속성이 변경되고 어떤 것이 실제로 동일하며 __dict__ 속성이 업데이트되는 방식을 확인할 수 있습니다.

(참고 :... 하지__dict__ 자신을 속성 수정하지 일반적으로되지 않는 다른 방법을 내장하여 봅시다 중 하나를 읽고 기능이 그것을 처리하기 위해, 어떤 방법으로 그것을 사용하지 않는)

관련 문제