Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Jonathan Fine

Jonathan Gardner wrote:

On Aug 21, 9:09 am, alex23 wuwe...@gmail.com wrote:

On Aug 21, 11:36 pm, Jonathan Fine jf...@pytex.org wrote:

class ColourThing(object):
@apply
def rgb():
def fset(self, rgb):
self.r, self.g, self.b = rgb
def fget(self):
return (self.r, self.g, self.b)
return property(**locals())



This is brilliant. I am going to use this more often. I've all but
given up on property() since defining get_foo, get_bar, etc... has
been a pain and polluted the namespace.



I think we can do better, with a little work.  And also solve the 
problem that 'apply' is no longer a builtin in Python3.


Here's my suggestion:
===
import wibble # Informs reader we're doing something special here.

class ColourThing(object):

@wibble.property
def rgb():
'''This is the docstring for the property.'''
def fset(self, rgb):
self.r, self.g, self.b = rgb
def fget(self):
return (self.r, self.g, self.b)
return locals()
===

And here's wibble.property()
===
_property = property  # Avoid collision.
def property(fn):
return _property(doc=fn.__doc__, **fn())
===

We can add apply() to the wibble module.  By the way, 'wibble' is a 
placeholder to the real name.  Any suggestions?


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


Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Leonhard Vogt



Why I've personally stopped using it: I've always had the impression
that decorators were intended to provide a convenient and obvious way
of augmenting functions. Having one that automatically executes the
function at definition just runs counter to the behaviour I expect
from a decorator. Especially when direct assignment... foo = foo
() ...is a far more direct and clear way of expressing exactly what is
happening.


if you have to define it yourself, you could call it store_result or
something else instead of apply.

@store_result
def tags():
return result

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


Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Steven D'Aprano
On Sat, 22 Aug 2009 08:09:52 +0100, Jonathan Fine wrote:

 Jonathan Gardner wrote:
 On Aug 21, 9:09 am, alex23 wuwe...@gmail.com wrote:
 On Aug 21, 11:36 pm, Jonathan Fine jf...@pytex.org wrote:

 class ColourThing(object):
 @apply
 def rgb():
 def fset(self, rgb):
 self.r, self.g, self.b = rgb
 def fget(self):
 return (self.r, self.g, self.b)
 return property(**locals())


 This is brilliant. I am going to use this more often. I've all but
 given up on property() since defining get_foo, get_bar, etc... has
 been a pain and polluted the namespace.
 
 
 I think we can do better, with a little work.  And also solve the
 problem that 'apply' is no longer a builtin in Python3.

There's a standard idiom for that, using the property() built-in, for 
Python 2.6 or better.

Here's an example including a getter, setter, deleter and doc string, 
with no namespace pollution, imports, or helper functions or deprecated 
built-ins:

class ColourThing(object):
@property
def rgb(self):
Get and set the (red, green, blue) colours.
return (self.r, self.g, self.b)
@rgb.setter
def rgb(self, rgb):
self.r, self.g, self.b = rgb
@rgb.deleter
def rgb(self):
del self.r, self.g, self.b


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


Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Steven D'Aprano
On Sat, 22 Aug 2009 10:51:27 +0100, Jonathan Fine wrote:

 Steven D'Aprano wrote:
 
 There's a standard idiom for that, using the property() built-in, for
 Python 2.6 or better.
 
 Here's an example including a getter, setter, deleter and doc string,
 with no namespace pollution, imports, or helper functions or deprecated
 built-ins:
 
 class ColourThing(object):
 @property
 def rgb(self):
 Get and set the (red, green, blue) colours. return
 (self.r, self.g, self.b)
 @rgb.setter
 def rgb(self, rgb):
 self.r, self.g, self.b = rgb
 @rgb.deleter
 def rgb(self):
 del self.r, self.g, self.b
 
 
 Sorry, Steve, but I don't understand this.  In fact, I don't even see
 how it can be made to work.

Nevertheless, it does work, and it's not even magic. It's described (very 
briefly) in the docstring for property: help(property) will show it to 
you. More detail is here:

http://docs.python.org/library/functions.html#property

As for how it can work, it's not that difficult. All you need is for the 
setter and deleter methods to add an appropriate fset and fdel method to 
the property, then return it. Here's a toy example which may demonstrate 
the process (although unlike property, fget, fset and fdel don't have any 
special meanings):

class ToyProperty(object):
def __init__(self, fget, fset=None, fdel=None, fdoc=None):
if fdoc is None:
fdoc = fget.__doc__
self.fget = fget
self.fset = fset
self.fdel = fdel
def getter(self, fget):
self.fget = fget
return self
def setter(self, fset):
self.fset = fset
return self
def deleter(self, fdel):
self.fdel = fdel
return self


 Unless an exception is raised,
  @wibble
  def wobble():
  pass
 will make an assignment to wobble, namely the return value of wibble. So
 in your example above, there will be /three/ assignments to rgb.

Yes. A tiny inefficiency, which only occurs when the class is created. If 
you care about that, then (1) use the full form of property() where you 
supply the fget, fset and fdel arguments all at once, and (2) you really 
need to get out into the fresh air more *wink*



 Unless
 you do some complicated introspection (and perhaps not even then) surely
 they will clobber each other.

So what? The process is no weirder than:

x = ['fget']
x = x + ['fset']
x = x + ['fdel']



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


Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Jonathan Fine

Steven D'Aprano wrote:

On Sat, 22 Aug 2009 10:51:27 +0100, Jonathan Fine wrote:


Steven D'Aprano wrote:


There's a standard idiom for that, using the property() built-in, for
Python 2.6 or better.

Here's an example including a getter, setter, deleter and doc string,
with no namespace pollution, imports, or helper functions or deprecated
built-ins:

class ColourThing(object):
@property
def rgb(self):
Get and set the (red, green, blue) colours. return
(self.r, self.g, self.b)
@rgb.setter
def rgb(self, rgb):
self.r, self.g, self.b = rgb
@rgb.deleter
def rgb(self):
del self.r, self.g, self.b


Sorry, Steve, but I don't understand this.  In fact, I don't even see
how it can be made to work.


Nevertheless, it does work, and it's not even magic. It's described (very 
briefly) in the docstring for property: help(property) will show it to 
you. More detail is here:


http://docs.python.org/library/functions.html#property


My apologies.  I wasn't up to date with my Python versions:

| Changed in version 2.6: The getter, setter, and deleter
| attributes were added.

I was still thinking Python2.5 (or perhaps earlier?).  I still don't 
like it.  All those repetitions of 'rgb'.


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


Re: Using 'apply' as a decorator, to define constants

2009-08-22 Thread Jan Kaliszewski

21-08-2009 o 18:09:02 alex23 wuwe...@gmail.com wrote:


Unfortunately, apply() has been removed as a built-in in 3.x.


You can always implement it yourself :)

def apply(function, args=(), keywords={}):
return function(*args, **keywords)

--
Jan Kaliszewski (zuo) z...@chopin.edu.pl
--
http://mail.python.org/mailman/listinfo/python-list


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread alex23
On Aug 21, 11:36 pm, Jonathan Fine jf...@pytex.org wrote:
 It might seem odd to use 'apply' as a decorator, but it can make sense.

Yes, it's an idiom I've used myself for property declarations, but one
I find myself using less often:

class ColourThing(object):
@apply
def rgb():
def fset(self, rgb):
self.r, self.g, self.b = rgb
def fget(self):
return (self.r, self.g, self.b)
return property(**locals())

Unfortunately, apply() has been removed as a built-in in 3.x. I'm not
sure if it has been relocated to a module somewhere, there's no
mention of such in the docs.

 Without using 'apply' as a decorator one alternative is
      def tmp():
          value = []
          # complicated code
          return value
      tags = tmp()
      del tmp

You can save yourself the tidy up by using the same name for the
function  the label:

def tags():
value = []
# ...
return value
tags = tags()

 Like all uses of decorators, it is simply syntactic sugar.  It allows
 you to see, up front, what is going to happen.  I think, once I get used
 to it, I'll get to like it.

The question is, is it really that useful, or is it just a slight
aesthetic variation? Given that apply(f, args, kwargs) is identical to
f(*args, **kwargs), it's understandable that's apply() isn't seen as
worth keeping in the language.

Why I've personally stopped using it: I've always had the impression
that decorators were intended to provide a convenient and obvious way
of augmenting functions. Having one that automatically executes the
function at definition just runs counter to the behaviour I expect
from a decorator. Especially when direct assignment... foo = foo
() ...is a far more direct and clear way of expressing exactly what is
happening.

But that's all IMO, if you feel it makes your code cleaner and don't
plan on moving to 3.x any time soon (come on in! the water's great!),
go for it :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread Jonathan Fine

alex23 wrote:


Unfortunately, apply() has been removed as a built-in in 3.x. I'm not
sure if it has been relocated to a module somewhere, there's no
mention of such in the docs.


The old use of apply()


You can save yourself the tidy up by using the same name for the
function  the label:

def tags():
value = []
# ...
return value
tags = tags()


I don't like that because there's no hint at
def tags():
that this is /not/ the value of tags.


Like all uses of decorators, it is simply syntactic sugar.  It allows
you to see, up front, what is going to happen.  I think, once I get used
to it, I'll get to like it.


The question is, is it really that useful, or is it just a slight
aesthetic variation? Given that apply(f, args, kwargs) is identical to
f(*args, **kwargs), it's understandable that's apply() isn't seen as
worth keeping in the language.


Yes, I agree with that, completely.


Why I've personally stopped using it: I've always had the impression
that decorators were intended to provide a convenient and obvious way
of augmenting functions. 


Yes, that was the intended use case.


Having one that automatically executes the
function at definition just runs counter to the behaviour I expect
from a decorator. 


I'd expect the name of the decorator to explain what is going on.  If 
apply() were a well known part of the language, that would be fine.



Especially when direct assignment... foo = foo
() ...is a far more direct and clear way of expressing exactly what is
happening.


Actually, I think the decorator approach is clearer.  But that's just my 
opinion, and not with the benefit of a lot of experience.



But that's all IMO, if you feel it makes your code cleaner and don't
plan on moving to 3.x any time soon (come on in! the water's great!),
go for it :)


Thank you for your comments, Alex.  And particularly for telling me that 
apply() is no longer a builtin for Python 3.


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


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread Jonathan Gardner
On Aug 21, 6:36 am, Jonathan Fine jf...@pytex.org wrote:
     �...@apply
      def tags():
          value = []
          # complicated code
          return value


Is this different from:

tags = []
# complicated code

I can see the argument that you are cleaning up a lot of intermediary
variables upon return, though.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread Jonathan Gardner
On Aug 21, 9:09 am, alex23 wuwe...@gmail.com wrote:
 On Aug 21, 11:36 pm, Jonathan Fine jf...@pytex.org wrote:

 class ColourThing(object):
     @apply
     def rgb():
         def fset(self, rgb):
             self.r, self.g, self.b = rgb
         def fget(self):
             return (self.r, self.g, self.b)
         return property(**locals())


This is brilliant. I am going to use this more often. I've all but
given up on property() since defining get_foo, get_bar, etc... has
been a pain and polluted the namespace.


 Unfortunately, apply() has been removed as a built-in in 3.x. I'm not
 sure if it has been relocated to a module somewhere, there's no
 mention of such in the docs.

apply = lambda f: f()

It's one of those functions that is easier to define than import.


 Why I've personally stopped using it: I've always had the impression
 that decorators were intended to provide a convenient and obvious way
 of augmenting functions. Having one that automatically executes the
 function at definition just runs counter to the behaviour I expect
 from a decorator. Especially when direct assignment... foo = foo
 () ...is a far more direct and clear way of expressing exactly what is
 happening.


If anyone reads the decorator and doesn't think this thing below is
defined as the result of this decorator function then they don't
understand decorators at all.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread alex23
Jonathan Gardner jgard...@jonathangardner.net wrote:
 This is brilliant. I am going to use this more often. I've all but
 given up on property() since defining get_foo, get_bar, etc... has
 been a pain and polluted the namespace.

Unfortunately I can't remember who I first learned it from - it was
definitely in a post to this group - otherwise all credit would be
their's.

 It's one of those functions that is easier to define than import.

And so obvious now :)

 If anyone reads the decorator and doesn't think this thing below is
 defined as the result of this decorator function then they don't
 understand decorators at all.

Well, it's not so much a question of the reader's intelligence as that
Python already has a readily identifiable assignment operator. Having
a second mechanism for assignment with no real similarity to the first
just adds cognitive friction to reading the code...not because the
reader doesn't understand what is happening, but because it's not
obvious _why_ this second form would have been chosen.

Nothing that couldn't be mitigated with a comment, I guess.

# @apply used to prevent having to repeat references

That would work for me.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Using 'apply' as a decorator, to define constants

2009-08-21 Thread Steven D'Aprano
On Fri, 21 Aug 2009 15:17:40 -0700, Jonathan Gardner wrote:

 Unfortunately, apply() has been removed as a built-in in 3.x. I'm not
 sure if it has been relocated to a module somewhere, there's no mention
 of such in the docs.
 
 apply = lambda f: f()
 
 It's one of those functions that is easier to define than import.

 apply = lambda f: f()
 __builtin__.apply(len, 'a')
1
 apply(len, 'a')
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: lambda() takes exactly 1 argument (2 given)


It's a little bit more difficult to define it *correctly*. Here's a 
working version of apply:


def apply(object, *args, **kwargs):
apply(object[, args[, kwargs]]) - value

Call a callable object with positional and keyword arguments.

 apply(max, 'one', 'two', 'three', 'four', key=len)
'three'


return object(*args, **kwargs)

Note that this:

* actually does what apply() is supposed to do;
* defines the function name, useful for tracebacks;
* has a docstring, useful for interactive use and documentation;
* includes an example suitable for automated testing with doctest.



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