program tip

Python : 클래스 및 인스턴스 변수 이해

radiobox 2020. 12. 30. 08:01
반응형

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']

나는 그 생각 energyskill내가 어떤 방법으로 그들을 선언 때문에, 클래스 변수했다. 동일한 방식으로 메서드 내에서 값을 수정합니다 ( self그의 선언에서 잘못되었을 수 있습니까?). 그러나 결과는 energy각 객체 (예 : 인스턴스 변수)에 대해 서로 다른 값을 사용하는 반면 skills공유 되는 것처럼 보입니다 (클래스 변수). 중요한 걸 놓친 것 같아요 ...


가변성을 기반으로 초기화 문제가 발생합니다.

첫째 , 수정. skillsenergy클래스 속성입니다. 인스턴스 속성의 초기 값으로 읽기 전용으로 간주하는 것이 좋습니다. 수업을 구축하는 고전적인 방법은 다음과 같습니다.

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

반응형