In class object, how to auto update attributes?

前端 未结 4 1639
我寻月下人不归
我寻月下人不归 2020-12-03 00:12

I have a class which has multiple attributes that are related, for example:

class SomeClass:
    def __init__(self, n=0):
        self.list = range(n)
               


        
相关标签:
4条回答
  • 2020-12-03 00:25

    You can also just use setter methods, like this:

    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))
    
    0 讨论(0)
  • 2020-12-03 00:35

    Ignacio's @property solution is great but it recalculates the list every time you reference listsquare - that could get expensive. Mathew's solution is great, but now you have function calls. You can combine these with the 'property' function. Here I define a getter and a setter for my_list (I just couldn't call it 'list'!) that generates listsquare:

    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
    

    This outputs:

    [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]
    
    0 讨论(0)
  • 2020-12-03 00:37

    Absolutely. But use a property instead.

    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
    

    Caching of the property value is left as an exercise for the reader.

    0 讨论(0)
  • 2020-12-03 00:51

    if updating one property due to an update on another property is what you're looking for (instead of recomputing the value of the downstream property on access) use property setters:

    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]
    
    0 讨论(0)
提交回复
热议问题