dippim wrote:
On Aug 14, 10:48 am, Dave Angel <da...@ieee.org> wrote:

dippim wrote:

On Aug 14, 2:34 am, Raymond Hettinger <pyt...@rcn.com> wrote:

[David]

I am new to Python and I have a question about descriptors.  If I have
a class as written below, is there a way to use descriptors to be
certain that the datetime in start is always before the one in end?

class foo(object):
  def __init__(self,a =one,b = None)
     self.start =
     self.end =

from datetime import datetime
c =atetime(2009,8,13,6,15,0)
d =atetime(2009,8,14,12,0,0)
afoo =oo(c,d)

For instance, if the following code were run, I would like to instance
of foo to switch the start and end times.

afoo.start =atetime(2010,8,13,6,15,0)

I was thinking of using the __set__ descriptor to catch the assignment
and reverse the values if necessary, but I can't figure out how to
determine which values is being set.

You're on the right track, but it is easier to use property() than to
write your own custom descriptor with __get__ and __set__.

class foo(object):
   def __init__(self,a =one,b = None):
       self._start =
       self._end =
   def get_start(self):
       return self._start
   def set_start(self, value):
       if self._end is None or value < self._end:
           self._start =alue
       else:
           self._end =alue
   start =roperty(get_start, set_start)
   def get_end(self):
       return self._end
   def set_end(self, value):
       if self._start is None or value > self._start:
           self._end =alue
       else:
           self._start =alue
   end =roperty(get_end, set_end)

Raymond

Raymond,
  This functionality is exactly what I was looking for. Thanks!  I'll
be using this to solve my problem.

  Now that I'm on the right track, I'm still a bit confused about how
__get__ and __set__ are useful.  Admittedly, I don't need to
understand them to solve this problem, but perhaps they may be useful
in the future.  If I wanted to solve this problem using __get__ and
__set__ could it be done?

Thanks Again!

DANGER- WILL ROBINSON!

Don't use this code as-is.  There is a nasty surprise waiting for the
caller when he sets start and end, and discovers that one of them gets
thrown out, and an old value still remains.

obj= foo(3, 5)
obj.start = 8
obj.end = 12
print obj.start, obj.end

will print out  3, 12.    Not what the caller expected.


You're right about this and I appreciate the warning, but I think what
Raymond was going for was directional accuracy without a great deal of
his time wasted on details.  The explanation served the purpose of
moving me forward using property() and I'm thankful for it.


Four fixes, in order of preference:
0) Trust your user to read and obey your docstrings.  This was what JM
was implying, by changing the names of the formal parameters.


Considering I am not the sharpest knife in the drawer, I don't wish to
start a philosophical discussion about the relative aptitude and
capabilities of the people who might use a class I build.  However, I
will say that as this particular requirement is imposed on this class
by the writer, shouldn't it be the writer's responsibility to enforce
it, especially, when the cost of enforcement is so low?


1)  make a new method that sets both values, making these two properties
readonly.  That new method would make sure the two parameters are
self-consistent.  Making the actual values readonly can be done with a
descriptor as well, or even a decorator.


2) Raise an exception in the getter methods if they're out of order
3) do the min/max logic on the getter methods, but I don't like that one
at all.

DaveA


I am in complete agreement with DaveA on this issue -- if you want the invariant, then have a routine that set's both at once.

The head-aches it would cause me, at least, to have to gyrate around whether I was making the object later or earlier in time (having to swap the order I assign stand and end, assuming I even know whether I'm going forward or backward without further checking... argh!) would quite possibly cause me to choose some other routine instead.

How about something like (untested):
    def set(self, start=None, end=None):
        if start is None:
            start = self.start
        if end is None:
            end = self.end
        if start > end:
            raise ValueError('blah blah')
        self.start = start
        self.end = end

This way you could still set only one, but have bounds checking in place.

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to