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.
