Python : 클래스 및 인스턴스 변수 이해
클래스 및 인스턴스 변수에 대한 오해가 있다고 생각합니다. 다음은 예제 코드입니다.
class Animal(object):
energy = 10
skills = []
def work(self):
print 'I do something'
self.energy -= 1
def new_skill(self, skill):
self.skills.append(skill)
if __name__ == '__main__':
a1 = Animal()
a2 = Animal()
a1.work()
print a1.energy # result:9
print a2.energy # result:10
a1.new_skill('bark')
a2.new_skill('sleep')
print a1.skills # result:['bark', 'sleep']
print a2.skills # result:['bark', 'sleep']
나는 그 생각 energy
과 skill
내가 어떤 방법으로 그들을 선언 때문에, 클래스 변수했다. 동일한 방식으로 메서드 내에서 값을 수정합니다 ( self
그의 선언에서 잘못되었을 수 있습니까?). 그러나 결과는 energy
각 객체 (예 : 인스턴스 변수)에 대해 서로 다른 값을 사용하는 반면 skills
공유 되는 것처럼 보입니다 (클래스 변수). 중요한 걸 놓친 것 같아요 ...
가변성을 기반으로 초기화 문제가 발생합니다.
첫째 , 수정. skills
및 energy
클래스 속성입니다. 인스턴스 속성의 초기 값으로 읽기 전용으로 간주하는 것이 좋습니다. 수업을 구축하는 고전적인 방법은 다음과 같습니다.
class Animal(object):
energy = 10
skills = []
def __init__(self,en=energy,sk=skills):
self.energy=en
self.skills=sk
....
그러면 각 인스턴스가 고유 한 속성을 갖게되고 모든 문제가 사라집니다.
둘째 ,이 코드에서 무슨 일이 일어나고 있습니까? 인스턴스별로 skills
공유되는 이유는 무엇 energy
입니까?
-=
연산자는 미묘하다. 가능한 경우 내부 할당을 위한 것입니다 . 여기서 차이점은 유형이 변경 가능하므로 내부 수정이 자주 발생 한다는 것입니다 .list
In [6]:
b=[]
print(b,id(b))
b+=['strong']
print(b,id(b))
[] 201781512
['strong'] 201781512
그래서 a1.skills
하고 a2.skills
또한 액세스 할 수있는 동일한 목록이 있습니다 Animal.skills
. 그러나 energy
비 변경 가능한 int
수정이 불가능하므로. 이 경우 새 int
객체가 생성되므로 각 인스턴스는 자체 energy
변수 사본을 관리 합니다.
In [7]:
a=10
print(a,id(a))
a-=1
print(a,id(a))
10 1360251232
9 1360251200
여기서 비결은 무엇을하는지 이해하는 것 self.energy -= 1
입니다. 정말 두 가지 표현입니다. 하나는 값을 가져오고 self.energy - 1
하나는 다시 할당합니다 self.energy
.
But the thing that's confusing you is that the references are not interpreted the same way on both sides of that assignment. When Python is told to get self.energy
, it tries to find that attribute on the instance, fails, and falls back to the class attribute. However, when it assigns to self.energy
, it will always assign to an instance attribute, even though that hadn't previously existed.
Upon initial creation both attributes are the same object:
>>> a1 = Animal()
>>> a2 = Animal()
>>> a1.energy is a2.energy
True
>>> a1.skills is a2.skills
True
>>> a1 is a2
False
When you assign to a class
attribute, it is made local to the instance:
>>> id(a1.energy)
31346816
>>> id(a2.energy)
31346816
>>> a1.work()
I do something
>>> id(a1.energy)
31346840 # id changes as attribute is made local to instance
>>> id(a2.energy)
31346816
The new_skill()
method does not assign a new value to the skills
array, but rather it appends
which modifies the list in place.
If you were to manually add a skill, then the skills
list would be come local to the instance:
>>> id(a1.skills)
140668681481032
>>> a1.skills = ['sit', 'jump']
>>> id(a1.skills)
140668681617704
>>> id(a2.skills)
140668681481032
>>> a1.skills
['sit', 'jump']
>>> a2.skills
['bark', 'sleep']
Finally, if you were to delete the instance attribute a1.skills
, the reference would revert back to the class attribute:
>>> a1.skills
['sit', 'jump']
>>> del a1.skills
>>> a1.skills
['bark', 'sleep']
>>> id(a1.skills)
140668681481032
Access the class variables through the class, not through self:
class Animal(object):
energy = 10
skills = []
def work(self):
print 'I do something'
self.__class__.energy -= 1
def new_skill(self, skill):
self.__class__.skills.append(skill)
Actually in you code a1.work(); print a1.energy; print a2.energy
when you are calling a1.work() an instance variable for a1 object is getting created with the same name that is 'energy'. And When interpreter comes to 'print a1.energy' it execute the instance variable of object a1. And when interpreter comes to 'print a2.energy' it execute the class variable, and since you have not changed the value of class variable it shows 10 as output.
ReferenceURL : https://stackoverflow.com/questions/35766834/python-understanding-class-and-instance-variables
'program tip' 카테고리의 다른 글
C ++ 스레드, std :: system_error-작업이 허용되지 않습니까? (0) | 2020.12.30 |
---|---|
Docker 컨테이너 및 메모리 소비 (0) | 2020.12.30 |
화살표 함수에 인수 배열이없는 이유는 무엇입니까? (0) | 2020.12.30 |
Git Bash (mintty)는 Windows 10 OS에서 매우 느립니다. (0) | 2020.12.30 |
모든 브라우저에 Windows Media Player 포함 (0) | 2020.12.30 |