On Wed, Aug 15, 2012 at 1:34 PM, Christopher Nelson <
[email protected]> wrote:

> > Python idiom is to not write getter / setters until (if) you need
> > them.  Use attributes instead.  Python Descriptors enable this.
> > http://docs.python.org/howto/descriptor.html
> >
> > class Foo():
> >    def __init__(self):
> >      self.something = None
> >
> > users of Foo can get / set .something as they wish.  Later on it's
> > decided that setting something needs some logic.  Foo is updated
> >
> >   def __init__(self):
> >     self._something = None
> >
> >     def set_something(self, val):
> >        # do stuff
> >        self._something = val
> >     def get_something(self):
> >        return self._something # or calculate it or whatever
> >
> >     something = property(get_something, set_something)
>
> Thanks.  That's fascinating and somewhat helpful but I'm not sure how
> to use it in my case.  My object model is kind of messy.  I have, very
> roughly, something like:
>
>     class TracPM:
>          def start(self, task):
>              ...do something to get start out of task...
>          def finish(self, task):
>              ...do something to get finish out of task...
>
> which is then called like:
>
>     for t in tasks:
>         start = pm.start(t)
>
> If I create TracPM.__get__() that doesn't relate to the start date, it
> relates to the TracPM class.  I guess what I need to do is:
>
>  * Create a ScheduleDate (or PMDate or something) class
>  * Give it __get__ and __set__ (and __delete__?) methods
>  * Make the dates in the task instances of that class
>  * Where I currently do "s = pm.start(t)" I'd do "s = t.start" (which
> would invoke the getter) and elsewhere I could do "t.start =
> <somedate>" to set it.
>
> Does that sound right?
>

Not quite -- you don't define __get__ and __set__ methods.  You define
methods with any name, and then magically turn them into a property (which
is a pair of setter/getter methods that magically act like an attribute
instead) using the built-in property() function (or the alternate
decorator-based spelling Olemis pointed out)

The problem in your case is that your getter is a function which takes one
argument -- because, as you say, it's actually a getter of a property on
the task, not on the TracPM class.  That means that you can't define the
property on the TracPM class.  Instead you would define the getter and
setter methods on whatever class "task" is an instance of, and then access
it like `foo = self.task.start; self.task.start = datetime(...)`.

But if "task" is a Trac ticket, or some other class whose definition you
don't control, then you can't really do that either.  At that point I guess
the "most elegant" way to deal with the problem would be by wrapping the
ticket in another class that adds the "start" and "finish" properties with
their getters and setters:

class TracPMTask(object):
  def __init__(self, task):
    self.task = task
  def _get_start(self):
    return however_you_do_this(self.task)
  def _set_start(self, start_datetime):
    however_you_do_that(self.task, start_datetime)
  start = property(_get_start, _set_start)

...which you would use like:

for t in tasks:
  start = TracPMTask(t).start
  TracPMTask(t).new_start = datetime.datetime.now()

...but, as you can see, this is now a pretty big departure from how you're
already doing things, and also begins to obfuscate what's going on more
than it helps.  So really, in your case, the "most Pythonic" thing to do is
probably to just keep it simple, and define a TracPM.set_start(self, task,
new_start) method -- then you don't have to change any of your code, and
it's totally clear to a reader what's going on.  It's perfectly idiomatic
Python as long as you don't call the method setStart :-)

-- 
You received this message because you are subscribed to the Google Groups "Trac 
Development" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/trac-dev?hl=en.

Reply via email to