2013-02-16 6 views
10

У меня есть класс, который имеет несколько атрибутов, которые связаны, например:В объекте класса, как автоматически обновлять атрибуты?

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). Это возможно? Есть Класс правильный выбор для этого?


Спасибо вам всем, но я полностью перегружен всеми различными ответами. Может ли кто-нибудь дать полное решение, чтобы я мог учиться писать самостоятельно?

Я хотел бы достичь класса Foo с 3-мя атрибутами length, list и listsquare, что:

  1. Если я a = Foo(3), я получаю a.length = 3, a.list = [0, 1, 2], a.listsquare = [0, 1, 4].
  2. Если у меня b = Foo().list = [5, 6], я получаю b.length = 2, b.listsquare = [25, 36].
  3. Если у меня c = Foo().listsquare = [4, 9], я получаю c.length = 2, c.list = [2, 3].
+2

Код, который вы предоставили нам не работает. классы определяются «классом» не «def» и инициализируются методом «def __init __ (self, ...)». Вы определили функцию с 1 обязательным параметром, называемым «self», и 1 необязательный параметр, называемый «n». Когда вы вызываете SomeClass (10), функция пытается назначить «список» объекту 10 и терпит неудачу. - О, похоже, вопрос переформатирован ... так что неважно. – tdelaney

+0

Извините, я внесла поправки. Я не очень хорошо знаком с этим сейчас. – LWZ

ответ

13

если обновление одного свойства из-за обновления на другую собственность, что вы ищете (вместо пересчета стоимости имущества ниже по течению на доступ) использовать свойство сеттеров:

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

Означает ли это, что мне нужно определить 3 свойства ('size',' list', 'listsquare'), поэтому, когда я обновляю один из них, остальные 2 будут обновляться? – LWZ

+0

это правильно. я обновил вышеупомянутый ответ, чтобы работать так, как вам хотелось, - атрибут размера больше необходим. –

4

Абсолютно. Но вместо этого используйте property.

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 

Кэширование ценности имущества оставлено в качестве упражнения для читателя.

+0

Отлично! А как насчет другого пути? Могу ли я определить 'a.listsquare' и получить' a.mylist'? – LWZ

+0

Да. Просто добавьте сеттер в свою собственность. –

2

Вы также можете просто использовать методы сеттера, как это:

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)) 
1

решение @property Игнасио является большим, но он пересчитывает список каждый раз, когда вы ссылаетесь listsquare - что может дорого обойтись. Решение Mathew замечательно, но теперь у вас есть вызовы функций. Вы можете комбинировать их с функцией «свойство». Здесь я определяю getter и setter для my_list (я просто не мог назвать его «list»!), Который генерирует 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 

Это выходы:

[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

благодаря указанию людей, я неправильно инициализировал список. – tdelaney

Смежные вопросы