복붙노트

[PYTHON] 클래스 객체에서 속성을 자동으로 업데이트하는 방법은 무엇입니까?

PYTHON

클래스 객체에서 속성을 자동으로 업데이트하는 방법은 무엇입니까?

관련된 여러 속성이있는 클래스가 있습니다. 예를 들면 다음과 같습니다.

class SomeClass:
    def __init__(self, n=0):
        self.list = range(n)
        self.listsquare = [ x**2 for x in self.list ]

정상적으로 객체를 만들면 문제가되지 않습니다.

a = SomeClass(10)

나는 2 개의 목록, a.list 및 a.listsquare를 얻을 것이다.

이제 빈 객체를 먼저 만들고 속성 하나를 지정하려면 다른 속성이 자동으로 업데이트되기를 원합니다. 예를 들어

b = SomeClass()
b.list = range(5,10)

b.listsquare가 자동으로 업데이트되고 다른 방법으로 (b.listsquare를 지정하고 b.list를 자동으로 업데이트)합니다. 이것이 가능한가? Class는 이것에 적합한 선택입니까?

당신 모두에게 감사합니다. 그러나 나는 모든 다른 대답에 완전히 압도되어 있습니다. 누구든지 완벽한 솔루션을 제공 할 수 있으므로 직접 작성해 볼 수 있습니까?

3 가지 속성 길이, list 및 listsquare를 가진 클래스 Foo를 얻고 싶습니다.

해결법

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

    1.다른 속성의 업데이트로 인해 하나의 속성을 업데이트하는 것이 원하는 경우 (액세스 할 때 다운 스트림 속성의 값을 다시 계산하는 대신) 속성 setter를 사용하십시오.

    다른 속성의 업데이트로 인해 하나의 속성을 업데이트하는 것이 원하는 경우 (액세스 할 때 다운 스트림 속성의 값을 다시 계산하는 대신) 속성 setter를 사용하십시오.

    class SomeClass(object):
        def __init__(self, n):
            self.list = range(0, n)
    
        @property
        def list(self):
            return self._list
        @list.setter
        def list(self, val):
            self._list = val
            self._listsquare = [x**2 for x in self._list ]
    
        @property
        def listsquare(self):
            return self._listsquare
        @listsquare.setter
        def listsquare(self, val):
            self.list = [int(pow(x, 0.5)) for x in val]
    
    >>> c = SomeClass(5)
    >>> c.listsquare
    [0, 1, 4, 9, 16]
    >>> c.list
    [0, 1, 2, 3, 4]
    >>> c.list = range(0,6)
    >>> c.list
    [0, 1, 2, 3, 4, 5]
    >>> c.listsquare
    [0, 1, 4, 9, 16, 25]
    >>> c.listsquare = [x**2 for x in range(0,10)]
    >>> c.list
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
  2. ==============================

    2.전혀. 대신에 속성을 사용하십시오.

    전혀. 대신에 속성을 사용하십시오.

    class SomeClass(object):
      def __init__(self, n=5):
        self.mylist = range(n)
    
      @property
      def listsquare(self):
        return [ x**2 for x in self.mylist ]
    
    a = SomeClass()
    a.mylist = [4, 5, 8]
    print a.listsquare
    

    속성 값의 캐싱은 독자의 연습 문제로 남겨 둡니다.

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

    3.다음과 같이 setter 메서드를 사용할 수도 있습니다.

    다음과 같이 setter 메서드를 사용할 수도 있습니다.

    class SomeClass:
        def __init__(self, n=5):
            self.set_list(range(n))
    
        def set_list(self, n):
            self.list = n
            self.listsquare = [ x**2 for x in self.list ]
    
    b = SomeClass()
    b.set_list(range(5,10))
    
  4. ==============================

    4.Ignacio의 @property 솔루션은 훌륭하지만 listsquare를 참조 할 때마다 목록을 다시 계산하므로 비용이 많이 듭니다. Mathew의 솔루션은 훌륭하지만 이제 함수 호출이 있습니다. 이들을 '속성'기능과 결합 할 수 있습니다. 여기에 listter를 생성하는 my_list에 대한 getter 및 setter를 정의합니다 ( 'list'라고 부를 수는 없습니다!).

    Ignacio의 @property 솔루션은 훌륭하지만 listsquare를 참조 할 때마다 목록을 다시 계산하므로 비용이 많이 듭니다. Mathew의 솔루션은 훌륭하지만 이제 함수 호출이 있습니다. 이들을 '속성'기능과 결합 할 수 있습니다. 여기에 listter를 생성하는 my_list에 대한 getter 및 setter를 정의합니다 ( 'list'라고 부를 수는 없습니다!).

    class SomeClass(object):
    
        def __init__(self, n=5):
            self.my_list = range(n)
    
        def get_my_list(self):
            return self._my_list
    
        def set_my_list(self, val):
            self._my_list = val
            # generate listsquare when my_list is updated
            self.my_listsquare = [x**2 for x in self._my_list]
    
        # now my_list can be used as a variable
        my_list = property(get_my_list, set_my_list, None, 'this list is squared')
    
    x = SomeClass(3)
    print x.my_list, x.my_listsquare
    x.my_list = range(10)
    print x.my_list, x.my_listsquare
    

    이 결과는 다음과 같습니다.

    [0, 1, 2] [0, 1, 4]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    
  5. from https://stackoverflow.com/questions/14916284/in-class-object-how-to-auto-update-attributes by cc-by-sa and MIT license