Python property does not use setter when setting the value in the constructor

Question:

I have a class with a constructor and a couple of properties

class Foo(object):
    def __init__(self, value1):
        self._value1 = value1

    @property
    def value1(self):
        return self._value1

    @property.setter
    def value1(self, value):
         assert value == 1
         self._value1 = value

Now when I set value1 in on creation of the object the setter is not used. I noticed this because assertions were not called when entering the wrong values.

How can I make the values set in the constructor make use of the setter?

Asked By: Johan Vergeer

||

Answers:

You’re explicitly bypassing the setter by setting the underlying variable, rather than using the property. Drop the underscore.

def __init__(self, value1):
    self.value1 = value1
Answered By: Daniel Roseman

Solution:

class Foo(object):
    def __init__(self, value1 = 0):
        self.value1 = value1    # Calling Set Property

    @property
    def value1(self):
        return self.__value1

    @property.setter
    def value1(self, value):
         assert value == 1
         self.__value1 = value

A few other examples:

Example 1

class Product(object):
    
    def __init__(self, price = 0.0):
        self.price = price
    
    def get_price(self):
        return self.__price
    
    def set_price(self, value):
        if value < 0:
            raise ValueError("Price cannot be negative")
        self.__price = value
    
    price = property(get_price, set_price)

Example 2

class Product(object):

    def __init__(self, price = 0.0, name = ""):
        self.price = price
        self.name = name
    
    # property for __price attribute 
    @property
    def price(self):
        return self.__price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError("Price cannot be negative")
        self.__price = value

    # property for __name attribute 
    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        for ch in value:
            if ch.isdigit():
                raise Exception("Enter valid product name")
        self.__name = value
Answered By: Muhammad Rizwan
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.