44

I have a class with an attribute I wish to turn into a property, but this attribute is set within __init__. Not sure how this should be done. Without setting the property in __init__ this is easy and works well

import datetime

class STransaction(object):
    """A statement transaction"""
    def __init__(self):
        self._date = None

    @property
    def date(self):
        return self._date

    @date.setter
    def date(self, value):
        d = datetime.datetime.strptime(value, "%d-%b-%y")
        self._date = d

st = STransaction()
st.date = "20-Jan-10"

But once initialization needs to occur in __init__ it gets more complicated and I am not sure of the correct course of action.

class STransaction(object):
    """A statement transaction"""
    def __init__(self, date):
        self._date = None

Strangely to me, the following seems to work but smells very bad.

class STransaction(object):
    """A statement transaction"""
    def __init__(self, date):
        self._date = None
        self.date = date

    @property
    def date(self):
        return self._date

    @date.setter
    def date(self, value):
        d = datetime.datetime.strptime(value, "%d-%b-%y")
        self._date = d

What is the correct way to go about setting properties in __init__?

Thanks, Aaron.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Aaron Barclay
  • 885
  • 2
  • 8
  • 9
  • 1
    In general, is there any reason to set `self._date = None` before updating the property since it will be immediately overwritten with the new value? – Kirk Strauser Oct 15 '10 at 13:39
  • No. It only makes sense if the second line is absent to prevent the getter being called with no attribute "_date" set – nerdoc Nov 17 '13 at 14:52

2 Answers2

31

I do not see any real problem with your code. In __init__, the class is fully created and thus the properties accessible.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Florian Mayer
  • 3,041
  • 24
  • 17
  • Ok, so perhaps I am looking at this the wrong way. At the point of __init__ is the property already created so my call to self.date is accessing via the property is the same way that my call to st.date is? – Aaron Barclay Oct 15 '10 at 12:01
  • 11
    Yes, exactly (why does Stackoverflow dislike short, to-the-point messages? - it refused to post just "Yes, exactly"). – Florian Mayer Oct 15 '10 at 12:03
  • +1 Perfectly right. I would add that the self._date = None in __init__ is really useless in this code (You can in some cases put the initialization of properties hidden variables in the getter using RAII ( `if not hasattr(self,_smth): do initialization...`) – ThR37 Oct 15 '10 at 12:05
10
class STransaction(object):
    """A statement transaction"""
    def __init__(self, date):
        self._date = None #1
        self.date = date  #2

If you want to set the proxy field self._date without executing of your setter use the #1 line. If you would like to execute the setter at startup too use the #2. Both ways are correct, it's just a matter of what do you want to do.

Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
  • 3
    Why would you want to set `_date` to `None` when init clearly is called with some particular `date`? You should store the correct value, hence #1 is not viable. – Nas Banov Dec 08 '12 at 20:09