En Wed, 14 May 2008 18:15:41 -0300, David C. Ullrich <[EMAIL PROTECTED]> 
escribió:

> Having a hard time phrasing this in the form
> of a question...
>
> The other day I saw a thread where someone asked
> about overrideable properties and nobody offered
> the advice that properties are Bad. So maybe we've
> got over that. I suppose properties could have
> Bad consequences if a user doesn't know they exist
> and think that a certain property of an object is
> just an ordinary attribute. But that applies to
> almost any aspect of any language.

Which "bad consequences" are you thinking of? Apart from the user not being 
aware of the complexity of certain operations, or a getter/setter very 
time-consuming (in that case I'd use public getXXX/setXXX functions instead, to 
emphasize that "something" is happening, not just an attribute lookup)

> If a person comes from, say, Object Pascal (Delphi)
> then properties are hard to live without. The

You should read the article "Python is not Java" if you haven't done it yet.
http://dirtsimple.org/2004/12/python-is-not-java.html

> other day I decided I wanted what OP calls an
> "indexed property" or "array property". Couldn't
> figure out how to make a _property_ behave that way.
> So I read a little bit about descriptors, and a
> few minutes later I had an indexedproperty thing
> that works just like property, except it gives
> an indexed property! This is just too cool.
>
> Why? For example, a Matrix should have a row[n]
> property allowing things like
>
> m.row[0] = m.row[1] + m.row[2]
>
> Ok, you could do _that_ by just making row
> an ordinary list of Row objects. But then
> you'd have to say
>
> m.row[0] = Row([1,2,3])
>
> where I want to be able to say
>
> m.row[0] = [1,2,3]
>
> and have the Row created automatically.

One could make *row* an object with a custom __getitem__/__setitem__ in this 
case. But I prefer to have as little magic as possible on my objects: if it 
says m.row[0] = [1,2,3] I expect m.row[0] to actually *be* that list (whenever 
possible), and not any other object initialized from the [1,2,3] arguments. 
(Maybe this is some overreaction against C++ "magic" constructors and such 
horrible things...)

> _Also_ with these indexed properties my Matrix
> can have m.row[j] and m.col[k] that look exactly
> the same to a client - we don't want to store a
> list of rows internally and also store the same
> data in a list of columns. Too cool.

The same can be achieved having m.row and m.col be custom objects like I said 
above.

> Hmm, none of that's a valid excuse for a post here.
> Um, right, here we go: Anyone see problems or
> possible improvements with the implementation
> of indexedproperty below?

Note that the property object (or your indexedproperty) is a *class* attribute. 
That is, shared among all instances.

> class indexedproperty(object):
>   def __init__(self, getitem=None, setitem=None):
>     self.getitem = getitem
>     self.setitem = setitem
>
>   def __get__(self, obj, owner):
>     self.obj = obj
>     return self

Here is the problem. You can't store "obj" in "self" because it is shared among 
all instances. Your examples don't show any problem because all property 
accesses are immediately followed by a getitem access using the same object. 
Try this:

x = AClass()
y = AClass()
x.cell[0,0] = 1
print x.cell[1,1]   # output: 0
y.cell[x.cell[0,0], x.cell[0,0]] = 2
print y.cell[1,1]   # should be 2, still 0
print x.cell[1,1]   # should still be 0, but changed, now 2

A workaround would be to return another object in __get__ instead of self, 
which remembers the "obj" instance, or a closure, or...
But I don't really see the point, it's a lot easier to use another object for 
.cell (it's more clear, doesn't break encapsulation, divides 
responsabilities...)

class Matrix2x2(object):
   def __init__(self):
     self.cells = [[0,0], [0,0]]

   def __setitem__(self, (row, col), value):
     self.cells[row][col] = value

   def __getitem__(self, (row, col)):
     return self.cells[row][col]

class AClass(object):
   def __init__(self):
     self.cell = Matrix2x2()


-- 
Gabriel Genellina

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

Reply via email to