Re: [Python-Dev] RFC: readproperty
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
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
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
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
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
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
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
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
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
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
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