복붙노트

[PYTHON] 왜 속성 참조가 파이썬 상속과 같은 역할을합니까? [복제]

PYTHON

왜 속성 참조가 파이썬 상속과 같은 역할을합니까? [복제]

다음은 이상하게 보입니다. 기본적으로 somedata 속성은 the_base_class에서 상속 된 모든 클래스간에 공유 된 것처럼 보입니다.

class the_base_class:
    somedata = {}
    somedata['was_false_in_base'] = False


class subclassthing(the_base_class):
    def __init__(self):
            print self.somedata


first = subclassthing()
{'was_false_in_base': False}
first.somedata['was_false_in_base'] = True
second = subclassthing()
{'was_false_in_base': True}
>>> del first
>>> del second
>>> third = subclassthing()
{'was_false_in_base': True}

__init__ 함수에서 self.somedata를 정의하는 것은 분명히이 문제를 해결하는 올바른 방법입니다 (각 클래스는 자신의 somedata dict를 가지고 있습니다).하지만 언제 그런 행동이 바람직합니까?

해결법

  1. ==============================

    1.네가 맞다. 클래스 정의시 생성되기 때문에 클래스의 모든 인스턴스와 서브 클래스가 공유된다. 선

    네가 맞다. 클래스 정의시 생성되기 때문에 클래스의 모든 인스턴스와 서브 클래스가 공유된다. 선

    somedata = {}
    somedata['was_false_in_base'] = False
    

    클래스가 정의 될 때, 즉 인터프리터가 클래스 서술문을 만날 때 - 인스턴스가 생성되지 않을 때 (자바의 정적 이니셜 라이저 블록을 생각할 때) 실행되지 않습니다. 속성이 클래스 인스턴스에 없으면 클래스 객체가 속성을 검사합니다.

    클래스 정의 시간에 다음과 같이 임의의 코드를 실행할 수 있습니다.

     import sys
     class Test(object):
         if sys.platform == "linux2":
             def hello(self):
                  print "Hello Linux"
         else:
             def hello(self):
                  print "Hello ~Linux"
    

    Linux 시스템에서 Test (). hello ()는 Hello Linux를 인쇄하고 다른 모든 시스템에서는 다른 문자열이 인쇄됩니다.

    반대로 __init__의 객체는 인스턴스 생성시 생성되며 인스턴스에만 속합니다 (자체에 할당 된 경우).

    class Test(object):
        def __init__(self):
            self.inst_var = [1, 2, 3]
    

    인스턴스가 아닌 클래스 객체에 정의 된 객체는 많은 경우에 유용 할 수 있습니다. 예를 들어 클래스의 인스턴스를 캐싱하여 동일한 멤버 값을 가진 인스턴스를 공유 할 수 있습니다 (불변이라고 가정).

    class SomeClass(object):
        __instances__ = {}
    
        def __new__(cls, v1, v2, v3):
            try:
                return cls.__insts__[(v1, v2, v3)]
            except KeyError:
                return cls.__insts__.setdefault(
                   (v1, v2, v3), 
                   object.__new__(cls, v1, v2, v3))
    

    주로 메타 클래스 또는 일반 팩토리 메서드와 함께 클래스 본문에 데이터를 사용합니다.

  2. ==============================

    2.보고있는 동작의 일부는 bool과 같은 간단한 데이터 형식과 달리 somedata가 dict 일 때 발생합니다.

    보고있는 동작의 일부는 bool과 같은 간단한 데이터 형식과 달리 somedata가 dict 일 때 발생합니다.

    예를 들어 다르게 동작하는이 예제를 보자.

    class the_base_class:
        somedata = False
    
    class subclassthing(the_base_class):
        def __init__(self):
            print self.somedata
    
    
    >>> first = subclassthing()
    False
    >>> first.somedata = True
    >>> print first.somedata
    True
    >>> second = subclassthing()
    False
    >>> print first.somedata
    True
    >>> del first
    >>> del second
    >>> third = subclassthing()
    False
    

    이 예제가 질문에서 주어진 것과 다르게 동작하는 이유는 first.somedata에 새로운 값 (객체 True)이 주어지기 때문입니다. 반면 첫 번째 예제에서는 first.somedata에서 참조하는 dict 객체 (그리고 다른 객체 서브 클래스 인스턴스)가 수정 중입니다.

    더 명확히하기 위해이 답변에 대한 Torsten Marek의 의견을 참조하십시오.

  3. ==============================

    3.나는 이것을 이해하는 가장 쉬운 방법 (행동을 예측할 수 있도록)은 당신이 그것을 그렇게 정의한다면 당신의 somedata가 클래스의 속성이지 그 클래스의 인스턴스가 아니라는 것을 깨닫는 것입니다.

    나는 이것을 이해하는 가장 쉬운 방법 (행동을 예측할 수 있도록)은 당신이 그것을 그렇게 정의한다면 당신의 somedata가 클래스의 속성이지 그 클래스의 인스턴스가 아니라는 것을 깨닫는 것입니다.

    당신의 예제에서 당신은 그 이름에 할당하지 않았지만 그것을 사용하여 사전을 찾아서 항목 (키, 값)을 할당했기 때문에 항상 유일한 somedata가 항상 존재합니다. 그것은 파이썬 인터프리터가 어떻게 작동하고 처음에는 혼란 스러울 수 있는지에 대한 결과 인 잡았다.

  4. from https://stackoverflow.com/questions/206734/why-do-attribute-references-act-like-this-with-python-inheritance by cc-by-sa and MIT license