5

I have the following code that uses two simple properties:

class Text(object):

    @property
    def color(self):
        return 'blue'

    @property
    def length(self):
        return 22

t = Text()
print t.color

When I run this, it obviously returns blue. But how can I update the value of color on the fly later in the code? I.e. when I try to do:

t = Text()
print t.color
t.color = 'red'
print t.color

It fails with a can't set attribute error. Is there a way to modify the value of a property?

EDIT:

If the above code is rewritten to use setters as in williamtroup's answer, what is the advantage of simply shortening it to:

class Text(object):

    def __init__(self):
        self.color = self.add_color()
        self.length = self.add_length()

    def add_color(self):
        return 'blue'

    def add_length(self):
        return 22
mart1n
  • 5,969
  • 5
  • 46
  • 83

1 Answers1

7

You need a setter for the property and a class variable to store the data.

With your example:

class Text(object):

    def __init__(self):
        self._color = "blue"
        self._length = 12

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value

    @property
    def length(self):
        return self._length

    @length.setter
    def length(self, value):
        self._length = value
William Troup
  • 12,739
  • 21
  • 70
  • 98
  • If rewritten using setters, what's the advantage over simply using attributes? See my edit to the question. – mart1n Mar 16 '16 at 08:03
  • Refer to this question: http://stackoverflow.com/questions/7374748/whats-the-difference-between-a-python-property-and-attribute. That should tell you everything you need. – William Troup Mar 16 '16 at 08:06
  • Right, I understand the difference, but why would you use one over the other? Also, if I want a default value computed based on some logic, I would need three functions: two properties, getter and setter, and one more function to fill `self._color` with a value based on that logic. That's three functions over just one when using attributes. – mart1n Mar 16 '16 at 08:12
  • The setter is the function to fill `self._color` yet. – Chickenmarkus Mar 16 '16 at 08:15
  • Even though __init__() is technically a function, its actually the constructor for the class. You can do it either way, I prefer the "setter" approach as it allows me to practice good encapsulation rules (yes, even in python). – William Troup Mar 16 '16 at 08:16
  • Sorry, I guess I'm not asking this clearly. I'm wondering how to modify the code to basically have two setters. One setter that fills in `self._color` with some color, say a random one from a given list, and another setter that allows me to directly set the color to a chosen value via `t.color = 'red'`. – mart1n Mar 16 '16 at 08:19
  • That can be done from outside the class instance, as you would get the value sorted and then set it using the color() property. – William Troup Mar 16 '16 at 08:28