Re: [Python-Dev] RFC: readproperty

2005-09-29 Thread Jim Fulton
Guido van Rossum wrote:
 On 9/28/05, Jim Fulton [EMAIL PROTECTED] wrote:
 
...
 I think we need to be real careful with chosing a name -- in Jim's
 example, *anyone* could assign to Spam().eggs to override the value.
 The name readproperty is too close to readonlyproperty,

In fact, property creates read-only properties for new-style classes.
(I hadn't realized, until reading this thread, that for classic
classes, you could still set the attribute.)

  but
 read-only it ain't! Lazy also doesn't really describe what's going
 on.

I agree.

 I believe some folks use a concept of memo functions which resemble
 this proposal except the notation is different: IIRC a memo function
 is always invoked as a function, but stores its result in a private
 instance variable, which it returns upon subsequent calls. This is a
 common pattern. Jim's proposal differs because the access looks like
 an attribute, not a method call. Still, perhaps memoproperty would be
 a possible name.
 
 Another way to look at the naming problem is to recognize that the
 provided function really computes a default value if the attribute
 isn't already set. So perhaps defaultproperty?

Works for me.

Oleg Broytmann wrote:
  On Wed, Sep 28, 2005 at 10:16:12AM -0400, Jim Fulton wrote:
 
class readproperty(object):
 
  [skip]
 
 I do this often enough
 
 
 I use it since about 2000 often enough under the name CachedAttribute:
 
  http://cvs.sourceforge.net/viewcvs.py/ppa/qps/qUtils.py

Steven Bethard wrote:
  Jim Fulton wrote:
 
...
  I've also needed behavior like this a few times, but I use a variant
  of Scott David Daniel's recipe[1]:
 
  class _LazyAttribute(object):


Yup, the Zope 3 sources have something very similar:

http://svn.zope.org/Zope3/trunk/src/zope/cachedescriptors/property.py?view=markup

I actually think this does too much.  All it saves me, compared to what I 
proposed
is one assignment.  I'd rather make that assignment explicit.

Anyway, all I wanted with readproperty was a property that implemented only
__get__, as opposed to property, which implements __get__, __set__, and 
__delete__.

I'd be happy to call it readproprty or getproperty or defaulproperty or 
whatever. :)

I'd prefer that it's semantics stay fairly simple though.


Jim

-- 
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Guido van Rossum
On 9/28/05, Jim Fulton [EMAIL PROTECTED] wrote:
 Read descriptors (defining only __get__) and data descripttors have
 (defining __get__ and __set__) different semantics. In particular,
 read descriptors are overridden by instance data, while data
 descriptors are not.  A common use of read descriptors is for lazily
 computed data:

class readproperty(object):
Create a read descriptor from a function

def __init__(self, func):
self.func = func

def __get__(self, inst, class_):
if inst is None:
return self

return self.func(inst)

class Spam:

@readproperty
def eggs(self):
... expensive computation of eggs

self.eggs = result
return result

 When we ask for the eggs attribute the first time, we call the
 descriptor, which calls the eggs function.  The function sets the eggs
 attribute, overriding the descriptor. The next time the eggs attribute
 is accessed, the saved value will be used without calling the
 descriptor.

 I do this often enough that I think it would be useful to include it
 in python, either as a builtin (like property) or in the library.  (Or
 possibly by adding an option to property to generate a read
 descriptor.) I'd be happy to add this for 2.5.

 Thoughts?

I like the idea of adding this functionality somewhere. I do note that
the semantics were somewhat of an accident, required by backwards
compatibility with pre-2.2 method lookup semantics.

I think we need to be real careful with chosing a name -- in Jim's
example, *anyone* could assign to Spam().eggs to override the value.
The name readproperty is too close to readonlyproperty, but
read-only it ain't! Lazy also doesn't really describe what's going
on.

I believe some folks use a concept of memo functions which resemble
this proposal except the notation is different: IIRC a memo function
is always invoked as a function, but stores its result in a private
instance variable, which it returns upon subsequent calls. This is a
common pattern. Jim's proposal differs because the access looks like
an attribute, not a method call. Still, perhaps memoproperty would be
a possible name.

Another way to look at the naming problem is to recognize that the
provided function really computes a default value if the attribute
isn't already set. So perhaps defaultproperty?

(Sorry to turn this into a naming game, which is bound to produce 100s
of competing proposals that are totally unintuitive except to the
proposer. But naming is important.)

--
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Phillip J. Eby
At 10:16 AM 9/28/2005 -0400, Jim Fulton wrote:
I do this often enough that I think it would be useful to include it
in python, either as a builtin (like property) or in the library.  (Or
possibly by adding an option to property to generate a read
descriptor.) I'd be happy to add this for 2.5.

Thoughts?

You mean something like defaultproperty(func), where func(ob) is called at 
most once when there is no dictionary entry for the attribute?

I started using such properties with PEAK a few years ago, and found some 
corner cases that made me decide to stick with ones that have both __get__ 
and __set__.  Mostly those cases have to do with creating class-level 
properties, which can end up being inherited by subclasses if you don't 
include __set__.  Also of course you can't hook the setting of attributes 
without a __set__.

Of course, most people aren't likely to be creating metaclass properties, 
so it's probably not a big issue for the stdlib.  But I thought *you* might 
want to know about it, in case you hadn't already encountered the issue.  :)

The other issue I found with such properties is that I really wanted to be 
able to use functions that didn't rebind the attribute value directly, 
i.e., I wanted to be able to use lambdas for short computed property 
descriptions.  However, to make this work you have to know what attribute 
name(s) the property is stored under in the class, which then leads to 
other interesting complications.  So now I use a custom C type that knows 
its name and takes two functions (a filter for values set, and a function 
to compute the default).

Unfortunately, finding out a descriptor's name is non-trivial; it'd be nice 
if there were a descriptor hook __bind__(cls,name) that was called by 
classes during cls.__new__ or assignment to a class attribute, and which 
you could define to return a replacement descriptor.  It seems like one of 
the first metaclasses I end up writing in any new project is something to 
do this, and I believe Ian Bicking has encountered the same thing in e.g. 
SQLObject.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Michael Hudson
Phillip J. Eby [EMAIL PROTECTED] writes:

 Unfortunately, finding out a descriptor's name is non-trivial; it'd be nice 
 if there were a descriptor hook __bind__(cls,name) that was called by 
 classes during cls.__new__ or assignment to a class attribute, and which 
 you could define to return a replacement descriptor.  It seems like one of 
 the first metaclasses I end up writing in any new project is something to 
 do this, and I believe Ian Bicking has encountered the same thing in e.g. 
 SQLObject.

I've done this many times too, but I've never really felt the need to
propose a change to Python for it.  I guess one could modify the
descriptor protocol slightly, but is it worth it?  Hmm, dunno.

Cheers,
mwh

-- 
  First time I've gotten a programming job that required a drug
  test.  I was worried they were going to say you don't have
  enough LSD in your system to do Unix programming.   -- Paul Tomblin
   -- http://home.xnet.com/~raven/Sysadmin/ASR.Quotes.html
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Žiga Seilnacht
Michael Hudson mwh at python.net writes:

 
 Phillip J. Eby pje at telecommunity.com writes:
 
  Unfortunately, finding out a descriptor's name is non-trivial; it'd be nice 
  if there were a descriptor hook __bind__(cls,name) that was called by 
  classes during cls.__new__ or assignment to a class attribute, and which 
  you could define to return a replacement descriptor.  It seems like one of 
  the first metaclasses I end up writing in any new project is something to 
  do this, and I believe Ian Bicking has encountered the same thing in e.g. 
  SQLObject.
 
 I've done this many times too, but I've never really felt the need to
 propose a change to Python for it.  I guess one could modify the
 descriptor protocol slightly, but is it worth it?  Hmm, dunno.
 
 Cheers,
 mwh
 

You can use something like this to find a descriptor's name:

class Private(property):

def __init__(self, permission, fget=None, fset=None, fdel=None, doc=None):
fget = fget or 'r' in permission and self.default_fget or None
fset = fset or 'w' in permission and self.default_fset or None
fdel = fdel or 'd' in permission and self.default_fget or None
super(private, self).__init__(fget, fset, fdel, doc)

def get_attribute_name(self, instance):
my_name = None
for cls in instance.__class__.mro():
for attribute_name, attribute_object in cls.__dict__.iteritems():
if attribute_object is self:
my_name = attribute_name
break
if my_name is not None:
class_name = cls.__name__
break
attribute_name = '_%s__%s' % (class_name, my_name)
self.attribute_name = attribute_name
return attribute_name

def default_fget(self, instance):
try:
attribute_name = self.attribute_name
except AttributeError:
attribute_name = self.get_attribute_name(instance)
return getattr(instance, attribute_name)

def default_fset(self, instance, value):
try:
attribute_name = self.attribute_name
except AttributeError:
attribute_name = self.get_attribute_name(instance)
setattr(instance, attribute_name, value)

def default_fdel(self, instance):
try:
attribute_name = self.attribute_name
except AttributeError:
attribute_name = self.get_attribute_name(instance)
delattr(instance, attribute_name)

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Oleg Broytmann
On Wed, Sep 28, 2005 at 10:16:12AM -0400, Jim Fulton wrote:
class readproperty(object):
[skip]
 I do this often enough

   I use it since about 2000 often enough under the name CachedAttribute:

http://cvs.sourceforge.net/viewcvs.py/ppa/qps/qUtils.py

   (The current maintainer of the code is Denis Otkidach,
http://sourceforge.net/users/ods/ .)

   It seems many people reinvent this particular wheel. Which is
understandable.

   propertytools.py, anyone?

Oleg.
-- 
 Oleg Broytmannhttp://phd.pp.ru/[EMAIL PROTECTED]
   Programmers don't die, they just GOSUB without RETURN.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Phillip J. Eby
At 05:28 PM 9/28/2005 +, Žiga Seilnacht wrote:

You can use something like this to find a descriptor's name:
  snip

The given code fails if the same property appears under more than one name 
or is used in more than one class.  It also requires the property object to 
be mutable, and is subject to inter-thread race conditions in the case of 
modification of a class.  It also doesn't work for class-level descriptors 
(added to the class' class), and I'd prefer it to use the logical 
equivalent of ob.__dict__.setdefault() rather than setattr(ob,...) so that 
it's free of (simple) race conditions in the case where one thread sets the 
attribute while another is computing the default value.

While these aren't crippling limitations in a given application, I think 
the stdlib implementation should be a bit more robust, especially since 
none of these features is very hard to implement, once you know what's 
needed.  (And I already have a robust implementation that could be cribbed 
from.)

In any case, having a stdlib version that doesn't address those issues 
wouldn't be very useful for me, as it wouldn't allow me to replace my 
custom C descriptor and metaclass.  If we added __bind__ (or something like 
it) to the descriptor protocol I could get rid of *at least* that 
metaclass, and maybe others.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Barry Warsaw
On Wed, 2005-09-28 at 10:16, Jim Fulton wrote:

 When we ask for the eggs attribute the first time, we call the
 descriptor, which calls the eggs function.  The function sets the eggs
 attribute, overriding the descriptor. The next time the eggs attribute
 is accessed, the saved value will be used without calling the
 descriptor.
 
 I do this often enough that I think it would be useful to include it
 in python, either as a builtin (like property) or in the library.  (Or
 possibly by adding an option to property to generate a read
 descriptor.) I'd be happy to add this for 2.5.

I /must/ be missing something.  Why not just use property as a
decorator?

class C:
@property
def eggs(self):
print 'in eggs'
self.eggs = 7
return self.eggs

 c = C()
 c.eggs
in eggs
7
 c.eggs
7

-Barry



signature.asc
Description: This is a digitally signed message part
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Guido van Rossum
It doesn't work that way for new-style classes.

On 9/28/05, Barry Warsaw [EMAIL PROTECTED] wrote:
 On Wed, 2005-09-28 at 10:16, Jim Fulton wrote:

  When we ask for the eggs attribute the first time, we call the
  descriptor, which calls the eggs function.  The function sets the eggs
  attribute, overriding the descriptor. The next time the eggs attribute
  is accessed, the saved value will be used without calling the
  descriptor.
 
  I do this often enough that I think it would be useful to include it
  in python, either as a builtin (like property) or in the library.  (Or
  possibly by adding an option to property to generate a read
  descriptor.) I'd be happy to add this for 2.5.

 I /must/ be missing something.  Why not just use property as a
 decorator?

 class C:
 @property
 def eggs(self):
 print 'in eggs'
 self.eggs = 7
 return self.eggs

  c = C()
  c.eggs
 in eggs
 7
  c.eggs
 7

 -Barry



 -BEGIN PGP SIGNATURE-
 Version: GnuPG v1.4.1 (GNU/Linux)

 iQCVAwUAQzsX03EjvBPtnXfVAQK43QP/dRjW11myDXRdjXcPPuaxRQ2qtUlMyAJG
 26sedhmrF00rvKVh7U0RaGJ/Cq5iwgEbQRmXm1pbS8UKzNZxz55qGjVDXjp7Rwgr
 KJpJzz/UWVqVClRJJGDdgasRO8GUfxTYh2YPrmXaTDPLh3uscIwpwq1oapT1R4OH
 6xJYLrjAs9M=
 =mCyw
 -END PGP SIGNATURE-


 ___
 Python-Dev mailing list
 Python-Dev@python.org
 http://mail.python.org/mailman/listinfo/python-dev
 Unsubscribe: 
 http://mail.python.org/mailman/options/python-dev/guido%40python.org





--
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Phillip J. Eby
At 06:23 PM 9/28/2005 -0400, Barry Warsaw wrote:
I /must/ be missing something.  Why not just use property as a
decorator?

class C:
 @property
 def eggs(self):
 print 'in eggs'
 self.eggs = 7
 return self.eggs

  c = C()
  c.eggs
in eggs
7
  c.eggs
7

Because it only works in classic classes due to a bug in descriptor handling:

  class C(object):
@property
 def eggs(self):
   print 'in eggs'
   self.eggs = 7
   return self.eggs

  c=C()
  c.eggs
in eggs

Traceback (most recent call last):
   File pyshell#12, line 1, in -toplevel-
 c.eggs
   File pyshell#10, line 4, in eggs
 self.eggs = 7
AttributeError: can't set attribute


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] RFC: readproperty

2005-09-28 Thread Barry Warsaw
On Wed, 2005-09-28 at 19:14, Phillip J. Eby wrote:

 Because it only works in classic classes due to a bug in descriptor handling:

Blah. ;)
-Barry



signature.asc
Description: This is a digitally signed message part
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com