2014-12-05 2 views
2

Итак, я недавно нырнул в ООП, и до сих пор все идет гладко. Хотя у меня нет проблем как таковых, есть замечательная функция, которая, я надеюсь, существует, хотя я не могу найти документацию по указанной функции.Как изменить значение одного атрибута, изменив значение другого? (зависимые атрибуты)

При назначении атрибутов объектам я часто нахожу, что мне приходится изменять атрибуты, которые зависят от других, скажем, света и тьмы. Вот пример:

class shade: 

    def __init__(self, light): 
     self.light=light 
     self.darkness=100-light 

    def __str__(self): 
     return (str(self.light) + ',' + str(self.darkness)) 



>>> shade1=shade(30,70) 
>>> shade1.light 
30 
>>> shade1.darkness 
70 

Теперь, в то время как это круто и все, что я хотел бы тот же процесс происходит, но в пределах того же объекта, если изменение одного атрибута происходит. Если я сброшу свойство света (о, да), я хочу, чтобы тьма соответствовала incr/decr. Я могу сделать это с помощью функции, если она работает, чтобы изменить свойство света, возвращая новое значение света/темноты, но я бы хотел сделать это, если бы я изменил свойство света просто путем переустановки его значения , ж/из использования функций, например:

>>> shade1.light=50 
>>> shade1.light 
50 
>>> shade1.darkness 
50 

Кроме того, как я новичок в ООП, если кто-нибудь знает некоторые хорошие учебники, которые бы также массивное помощь.

Заранее спасибо.

+0

Прежде всего. ваш класс не будет работать. у подрядчика есть только один аргумент, и вы ставите два, когда делаете класс «тень» (30,70) ' – Marcin

+0

Я знаю, это было намеренно, отсутствие света - это темнота, это на 100% зависит от интенсивности света, поэтому я думал, что нужно установить интенсивность света и искупить интенсивность тьмы. Это отлично работает, если вы запустите его, кстати. – user2901512

+0

Его точка в том, что это не так, конструктор определяется как один аргумент, но вы проходите два. – tripleee

ответ

12

Определение darkness В качестве property

class shade: 
    def __init__(self, light): 
     self.light=light 

    @property 
    def darkness(self): 
     return 100 - self.light 

    def __str__(self): 
     return (str(self.light) + ',' + str(self.darkness)) 

Свойства внешне выглядят как атрибуты, но внутренне действуют как вызовы функций. Когда вы скажете s.darkness, он вызывается функцией, которую вы предоставили для ее свойства. Это позволяет поддерживать только одну переменную внутри.

Если вы хотите, чтобы иметь возможность изменить его, присвоив темноте, добавить setter для свойства

class shade: 
    def __init__(self, light): 
     self.light=light 

    @property 
    def darkness(self): 
     return 100 - self.light 

    @darkness.setter 
    def darkness(self, value): 
     self.light = 100 - value 

Таким образом фактически модифицирующего свет. Если вы никогда раньше не видели свойств, я бы рекомендовал бросить в некоторые print() s телам функций, чтобы вы могли видеть, когда они вызываются.

>>> s = shade(70) 
>>> s.light 
70 
>>> s.darkness 
30 
>>> s.light = 10 
>>> s.darkness 
90 
>>> s.darkness = 20 
>>> s.light 
80 
+1

Фантастический! Я знал, что эта функция должна существовать. Большое спасибо Райан! – user2901512

+0

@ user2901512 Добро пожаловать. FYI, на языках без этой функции (Java, C++ и т. Д.) Это было бы сделано с помощью private int для освещения и доступа к ним через вызовы методов, например 's.darkness()' и 's.light()', добавление уровня косвенности –

+0

Просто для nitpick, для нечетного значения для 'light' (например, 'foo', [], None, -999.) будет молча приниматься' __init __() 'и будет запускаться только исключение, когда вы впоследствии получаете доступ к «темноте» или называете '__str __()'. Вы можете захотеть, чтобы typecheck 'light' внутри' __init __() ' – smci

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