Re: [Python-Dev] PEP 309: Partial method application

2005-08-19 Thread Steven Bethard
Martin v. Löwis wrote:
 Steven Bethard wrote:
 I thought that:
   operator.attrgetter() was for obj.attr
   operator.itemgetter() was for obj[integer_index]
 
 
  My point exactly.  If we're sticking to the same style, I would expect that 
  for
  obj.method(*args, **kwargs)
  we would have something like:
  operator.methodcaller('method', *args, **kwargs)
 
 You might be missing one aspect of attrgetter, though. I can have
 
   f = operator.attrgetter('name', 'age')
 
 and then f(person) gives me (person.name, person.age). Likewise for
 itemgetter(1,2,3).
[snip]
 I don't know what the common use for
 attrgetter is: one or more attributes?

Well, in current Python code, I'd be willing to wager that it's one,
no more, since Python 2.4 only supports a single argument to
itemgetter and attrgetter.  Of course, when Python 2.5 comes out, it's
certainly possible that the multi-argument forms will become
commonplace.

I agree that an operator.methodcaller() shouldn't try to support
multiple methods.  OTOH, the syntax
methodcall.method(*args, **kwargs)
doesn't really lend itself to multiple methods either.

STeVe
-- 
You can wordify anything if you just verb it.
--- Bucky Katt, Get Fuzzy
___
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] PEP 309: Partial method application

2005-08-19 Thread Josiah Carlson

Steven Bethard [EMAIL PROTECTED] wrote:
 I agree that an operator.methodcaller() shouldn't try to support
 multiple methods.  OTOH, the syntax
 methodcall.method(*args, **kwargs)
 doesn't really lend itself to multiple methods either.

But that's OK, we don't want to be calling multiple methods anyways, do
we?  I'd personally like to see an example it makes sense if someone
says that we do.

 - Josiah

___
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] PEP 309: Partial method application

2005-08-19 Thread Raymond Hettinger
[Steven Bethard]
  I agree that an operator.methodcaller() shouldn't try to support
  multiple methods.  OTOH, the syntax
  methodcall.method(*args, **kwargs)
  doesn't really lend itself to multiple methods either.

[Josiah Carlson]
 But that's OK, we don't want to be calling multiple methods anyways,
do
 we?  I'd personally like to see an example it makes sense if someone
 says that we do.

If an obvious syntax doesn't emerge, don't fret.  The most obvious
approach is to define a regular Python function and supply that function
to the key= argument for list.sort() or sorted().

A virtue of the key= argument was reducing O(n log n) calls to just
O(n).  Further speed-ups are a false economy.  So there's no need to
twist syntax into knots just to get a C based method calling function.

Likewise with map(), if a new function doesn't fit neatly, take that as
a cue to be writing a plain for-loop.


Raymond

___
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] PEP 309: Partial method application

2005-08-19 Thread Martin v. Löwis
Josiah Carlson wrote:
 Steven Bethard [EMAIL PROTECTED] wrote:
 
I agree that an operator.methodcaller() shouldn't try to support
multiple methods.  OTOH, the syntax
methodcall.method(*args, **kwargs)
doesn't really lend itself to multiple methods either.
 
 
 But that's OK, we don't want to be calling multiple methods anyways, do
 we?  I'd personally like to see an example it makes sense if someone
 says that we do.

Several people argued that the version with a string method name
should be added for consistency. I only pointed out that doing
so would not be completely consistent.

Regards,
Martin
___
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


[Python-Dev] PEP 309: Partial method application

2005-08-18 Thread Ian Bicking
I missed the discussion on this 
(http://www.python.org/peps/pep-0309.html), but then 2.5 isn't out yet.

I think partial() misses an important use case of method getting, for 
instance:

 lst = ['A', 'b', 'C']
 lst.sort(key=partialmethod('lower'))

Which sorts by lower-case.  Of course you can use str.lower, except 
you'll have unnecessarily enforced a type (and excluded Unicode).  So 
you are left with lambda x: x.lower().

Here's an implementation:

 def partialmethod(method, *args, **kw):
 def call(obj, *more_args, **more_kw):
 call_kw = kw.copy()
 call_kw.update(more_kw)
 return getattr(obj, method)(*(arg+more_args), **call_kw)
 return call

This is obviously related to partial().  Maybe this implementation 
should be a classmethod or function attribute, partial.method().

-- 
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.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] PEP 309: Partial method application

2005-08-18 Thread Raymond Hettinger
[Ian Bicking]
 I think partial() misses an important use case of method getting, for
 instance:
 
  lst = ['A', 'b', 'C']
  lst.sort(key=partialmethod('lower'))

We've already got one:

   lst.sort(key=operator.attrgetter('lower'))


Raymond

___
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] PEP 309: Partial method application

2005-08-18 Thread Steven Bethard
Raymond Hettinger wrote:
 [Ian Bicking]
  I think partial() misses an important use case of method getting, for
  instance:
 
   lst = ['A', 'b', 'C']
   lst.sort(key=partialmethod('lower'))

 We've already got one:

lst.sort(key=operator.attrgetter('lower'))

Doesn't that just sort on the str.lower or unicode.lower method object?

py sorted(['A', u'b', 'C'], key=operator.attrgetter('lower'))
[u'b', 'C', 'A']
py sorted(['A', u'b', 'C'], key=partialmethod('lower')) # after
fixing arg - args bug
['A', u'b', 'C']

STeVe
--
You can wordify anything if you just verb it.
   --- Bucky Katt, Get Fuzzy
___
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] PEP 309: Partial method application

2005-08-18 Thread Raymond Hettinger
  [Ian Bicking]
   I think partial() misses an important use case of method getting,
for
   instance:
  
lst = ['A', 'b', 'C']
lst.sort(key=partialmethod('lower'))
 
  We've already got one:
 
 lst.sort(key=operator.attrgetter('lower'))
 
 Doesn't that just sort on the str.lower or unicode.lower method
object?

My mistake.  It sorts on the bound method rather than the results of
applying that method.


Raymond

___
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] PEP 309: Partial method application

2005-08-18 Thread Ian Bicking
Raymond Hettinger wrote:
instance:

 lst = ['A', 'b', 'C']
 lst.sort(key=partialmethod('lower'))

We've already got one:

   lst.sort(key=operator.attrgetter('lower'))

Doesn't that just sort on the str.lower or unicode.lower method
 object?
 
 My mistake.  It sorts on the bound method rather than the results of
 applying that method.

Then I thought it might be right to do 
partial(operator.attrgetter('lower')).  This, however, accomplishes 
exactly nothing.  I only decided this after actually trying it, though 
upon reflection partial(function) always accomplishes nothing.

I don't have any conclusion from this, but only mention it to 
demonstrate that callables on top of callables are likely to confuse.

-- 
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.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] PEP 309: Partial method application

2005-08-18 Thread Martin v. Löwis
Ian Bicking wrote:
 
  lst = ['A', 'b', 'C']
  lst.sort(key=partialmethod('lower'))
 
 Which sorts by lower-case.  Of course you can use str.lower, except 
 you'll have unnecessarily enforced a type (and excluded Unicode).  So 
 you are left with lambda x: x.lower().

For this specific case, you can use string.lower (which is exactly
what the lambda function does).

As for the more general proposal: -1 on more places to pass strings to
denote method/function/class names. These are ugly to type.

What I think you want is not a partial method, instead, you want to
turn a method into a standard function, and in a 'virtual' way.

So I would propose the syntax

  lst.sort(key=virtual.lower) # where virtual is functional.virtual

As for extending PEP 309: This PEP deliberately abstained from other
ways of currying, and instead only introduced the functional module.
If you want to see lazy functions in the standard library, you should
write a new PEP (unless there is an easy agreement about a single right
way to do this, which I don't see).

Regards,
Martin

P.S. It's not even clear that this should be added to functional,
as attrgetter and itemgetter are already in operator. But, perhaps,
they should be in functional.

___
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] PEP 309: Partial method application

2005-08-18 Thread Shane Hathaway
Martin v. Löwis wrote:
 So I would propose the syntax
 
   lst.sort(key=virtual.lower) # where virtual is functional.virtual

Ooh, may I say that idea is interesting!  It's easy to implement, too:

class virtual:
 def __getattr__(self, name):
 return lambda obj: getattr(obj, name)()
virtual = virtual()

Shane
___
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] PEP 309: Partial method application

2005-08-18 Thread Guido van Rossum
On 8/18/05, Martin v. Löwis [EMAIL PROTECTED] wrote:
 As for the more general proposal: -1 on more places to pass strings to
 denote method/function/class names. These are ugly to type.

Agreed.

 What I think you want is not a partial method, instead, you want to
 turn a method into a standard function, and in a 'virtual' way.
 
 So I would propose the syntax
 
   lst.sort(key=virtual.lower) # where virtual is functional.virtual

I like this, but would hope for a different name -- the poor word
'virtual' has been abused enough by C++.

 P.S. It's not even clear that this should be added to functional,
 as attrgetter and itemgetter are already in operator. But, perhaps,
 they should be in functional.

They feel related to attrgetter more than to partial.

-- 
--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] PEP 309: Partial method application

2005-08-18 Thread Brett Cannon
On 8/18/05, Guido van Rossum [EMAIL PROTECTED] wrote:
 On 8/18/05, Martin v. Löwis [EMAIL PROTECTED] wrote:
  As for the more general proposal: -1 on more places to pass strings to
  denote method/function/class names. These are ugly to type.
 
 Agreed.
 
  What I think you want is not a partial method, instead, you want to
  turn a method into a standard function, and in a 'virtual' way.
 
  So I would propose the syntax
 
lst.sort(key=virtual.lower) # where virtual is functional.virtual
 
 I like this, but would hope for a different name -- the poor word
 'virtual' has been abused enough by C++.
 

Yeah, me too.  Possible name are 'delayed', 'lazyattr', or just plain
'lazy' since it reminds me of Haskell.

  P.S. It's not even clear that this should be added to functional,
  as attrgetter and itemgetter are already in operator. But, perhaps,
  they should be in functional.
 
 They feel related to attrgetter more than to partial.
 

True, but the idea of lazy evaluation, at least for me, reminds me
more of functional languages and thus the functional module.

Oh, when should we think of putting reduce into functional?  I
remember this was discussed when it was realized reduce was the only
functional built-in that is not covered by itertools or listcomps.

-Brett
___
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] PEP 309: Partial method application

2005-08-18 Thread Raymond Hettinger
[Guido]
 They feel related to attrgetter more than to partial.

That suggests operator.methodcall()

___
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] PEP 309: Partial method application

2005-08-18 Thread Ian Bicking
Brett Cannon wrote:
What I think you want is not a partial method, instead, you want to
turn a method into a standard function, and in a 'virtual' way.

So I would propose the syntax

  lst.sort(key=virtual.lower) # where virtual is functional.virtual

I like this, but would hope for a different name -- the poor word
'virtual' has been abused enough by C++.

 
 
 Yeah, me too.  Possible name are 'delayed', 'lazyattr', or just plain
 'lazy' since it reminds me of Haskell.

I don't think there's anything particularly lazy about it.  It's like a 
compliment of attrgetter.  Where attrgetter is an inversion of getattr, 
partialmethod is an inversion of... well, of something that currently 
has no name.  There's kind of an implicit operation in obj.method() -- 
people will generally read that as a method call, not as the retrieval 
of a bound method and later invocation of that method.  I think that is 
why it's so hard to figure out how to represent this in terms of 
something like attrgetter -- we try to invert something (a method call) 
that doesn't exist in the language.


-- 
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.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] PEP 309: Partial method application

2005-08-18 Thread Nick Coghlan
Brett Cannon wrote:
What I think you want is not a partial method, instead, you want to
turn a method into a standard function, and in a 'virtual' way.

So I would propose the syntax

  lst.sort(key=virtual.lower) # where virtual is functional.virtual

I like this, but would hope for a different name -- the poor word
'virtual' has been abused enough by C++.
 
 Yeah, me too.  Possible name are 'delayed', 'lazyattr', or just plain
 'lazy' since it reminds me of Haskell.

Hmm, methodcall?

As in:
   lst.sort(key=methodcall.lower)

Where methodcall is something like what Shane described:

   class methodcall:
   def __getattr__(self, name):
   def delayedcall(*args, **kwds):
   return getattr(args[0], name)(*args[1:], **kwds)
   return delayedcall
   methodcall = methodcall()

 
 Oh, when should we think of putting reduce into functional?  I
 remember this was discussed when it was realized reduce was the only
 functional built-in that is not covered by itertools or listcomps.

I expected functional.map, functional.filter and functional.reduce to all 
exist in 2.5.

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
 http://boredomandlaziness.blogspot.com
___
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] PEP 309: Partial method application

2005-08-18 Thread Brett Cannon
On 8/18/05, Nick Coghlan [EMAIL PROTECTED] wrote:
 Brett Cannon wrote:

  Oh, when should we think of putting reduce into functional?  I
  remember this was discussed when it was realized reduce was the only
  functional built-in that is not covered by itertools or listcomps.
 
 I expected functional.map, functional.filter and functional.reduce to all
 exist in 2.5.
 

Itertools covers map, filter is covered by genexps.  'reduce' is the
only one that does not have an equivalent anywhere.  I guess we could
cross-link itertools.map into functional.map, but I would rather just
mention in the docs of one that it is located in the other module. 
And filter is just not worth it; that can definitely be covered in the
docs of the module.

-Brett
___
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] PEP 309: Partial method application

2005-08-18 Thread Josiah Carlson

Steven Bethard [EMAIL PROTECTED] wrote:
 
 Martin v. Löwis wrote:
  So I would propose the syntax
 
lst.sort(key=virtual.lower) # where virtual is functional.virtual
  
 Shane Hathaway wrote:
  class virtual:
   def __getattr__(self, name):
   return lambda obj: getattr(obj, name)()
  virtual = virtual()
 
 I think (perhaps because of the name) that this could be confusing.  I
 don't have any intuition that virtual.lower would return a function
 that calls the lower attribute instead of returning a function that
 simply accesses that attribute.
 
 If we're going to move away from the itemgetter() and attrgetter()
 style, then we should be consistent about it and provide a solution
 (or solutions) that answers all of these problems:
 obj.attr
 obj.attr(*args, **kwargs)
 obj[key]
 I'm not sure that there is a clean/obvious way to do this.

I thought that:
  operator.attrgetter() was for obj.attr
  operator.itemgetter() was for obj[integer_index]

That's almost all the way there.  All that remains is to have something
that gets any key (not just integers) and which handles function calls.

In terms of the function call semantics, what about:

   class methodcall:
   def __getattr__(self, name, *args, **kwds):
   def delayedcall(obj):
   return getattr(obj, name)(*args, **kwds)
   return delayedcall
   methodcall = methodcall()

 - Josiah

___
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] PEP 309: Partial method application

2005-08-18 Thread Steven Bethard
Josiah Carlson wrote:
 Steven Bethard [EMAIL PROTECTED] wrote:
  If we're going to move away from the itemgetter() and attrgetter()
  style, then we should be consistent about it and provide a solution
  (or solutions) that answers all of these problems:
  obj.attr
  obj.attr(*args, **kwargs)
  obj[key]
  I'm not sure that there is a clean/obvious way to do this.
 
 I thought that:
   operator.attrgetter() was for obj.attr
   operator.itemgetter() was for obj[integer_index]

My point exactly.  If we're sticking to the same style, I would expect that for
obj.method(*args, **kwargs)
we would have something like:
operator.methodcaller('method', *args, **kwargs)

The proposal by Martin v. Löwis is that this should instead look something like:
methodcall.method(*args, **kwargs)
which is a departure from the current attrgetter() and itemgetter()
idiom.  I'm not objecting to this approach, by the way.  I think with
the right name, it would probably read well.  I just think that we
should try to be consistent one way or the other.  If we go with
Martin v. Löwis's suggestion, I would then expect that the corrolates
to attrgetter() and itemgetter() would also be included, e.g.:
attrget.attr   (for obj.attr)
itemget[key]   (for obj[key])


STeVe
-- 
You can wordify anything if you just verb it.
--- Bucky Katt, Get Fuzzy
___
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] PEP 309: Partial method application

2005-08-18 Thread Martin v. Löwis
Steven Bethard wrote:
I thought that:
  operator.attrgetter() was for obj.attr
  operator.itemgetter() was for obj[integer_index]
 
 
 My point exactly.  If we're sticking to the same style, I would expect that 
 for
 obj.method(*args, **kwargs)
 we would have something like:
 operator.methodcaller('method', *args, **kwargs)

You might be missing one aspect of attrgetter, though. I can have

  f = operator.attrgetter('name', 'age')

and then f(person) gives me (person.name, person.age). Likewise for
itemgetter(1,2,3). Extending this to methodcaller is not natural;
you would have

  x=methodcaller(('open',['foo','r'],{}),('read',[100],{}),
 ('close',[],{}))

and then

  x(somestorage)

(I know this is not the typical open/read/close pattern, where you
 would normally call read on what open returns)

It might be that there is no use case for a multi-call methodgetter;
I just point out that a single-call methodgetter would *not* be
in the same style as attrgetter and itemgetter.

 attrget.attr   (for obj.attr)
 itemget[key]   (for obj[key])

I agree that would be consistent. These also wouldn't allow to get
multiple items and indices. I don't know what the common use for
attrgetter is: one or more attributes?

Regards,
Martin
___
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