[Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Michael O'Keefe
I had an idea on some new functionality I'd like to see offered
in the python object class. I did some searching on the list 
but I wouldn't doubt that someone has proposed something 
like this before as chaining method calls seems like something 
folks would want to do.

Specifically, I'd like to see a built-in shorthand to allow me to 
chain method calls even when a method call does not explicity 
return a reference to the instance of the object (self).

I have an example below. In this example, someFunc represents 
the current way of dealing with calling methods that modify an
object's state with no return value (if you found yourself doing 
this a lot, you might just write a wrapper function).

The function explicitReturn shows how things might go if python
implicitly returned self when no other return value was specified
(similar to Ruby). I'm not proposing this, but have included it for 
completeness.

The final two functions give some options for what I'm proposing
as a shorthand (ideally included in class object but used in a 
subclass of class list in this example). The first of the two functions, 
newFunc01, defines the method "_". I'm not crazy about this 
because it's not very descriptive but it is the shortest way I could
think of.

The second possible shorthand is in, newFunc02, which defines
the method "self_". I didn't want the method to be too long but my
intent was "apply the given method and return self". I used the trailing
underscore so as not to confuse with the self instance variable.

I'm sure there are other ways to do this as well but what do people
think? Has something like this come up before?

def someFunc():
a = list([8,9,7,1])
a.sort()
a.reverse()
a.pop(0)
return a

def explicitReturn():
a = ExplicitReturnList([8,9,7,1]).sort().reverse()
a.pop(0)
return a

def newFunc01():
return NewList([8,9,7,1])._('sort')._('reverse')._('pop',0)

def newFunc02():
return NewList([8,9,7,1]).self_('sort').self_('reverse').self_('pop',0)

class NewList(list):
def __init__(self,*args,**kwargs):
list.__init__(self,*args,**kwargs)
def _(self,methodName,*args,**kwargs):
method = getattr(self,methodName)
method(*args,**kwargs)
return self
def self_(self,methodName,*args,**kwargs):
method = getattr(self,methodName)
method(*args,**kwargs)
return self

class ExplicitReturnList(list):
def __init__(self,*args,**kwargs):
list.__init__(self,*args,**kwargs)
def sort(self):
super(ExplicitReturnList,self).sort()
return self
def reverse(self):
super(ExplicitReturnList,self).reverse()
return self

print someFunc()# returns [8, 7, 1]
print explicitReturn()  # returns [8, 7, 1]
print newFunc01()   # returns [8, 7, 1]
print newFunc02()   # returns [8, 7, 1]

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


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Michael O\'Keefe
Michael O'Keefe  okeefecreations.com> writes:

I kept playing with this since my last post went live and here is a 
little more thought on these ideas. After sitting with the "Zen of
Python" document (>>> import this), I'm maybe waffling on my
previous post already so I came up with a few more options
here.

Also, to play the devil's advocate, in terms of pure space, these
ideas don't necessarily decrease the total amount of typing (see
the length stackup at the end of the post) though they would allow
a trade for horizontal typing versus vertical (down the page) typing
making for compact looking code.

I suppose what would be nice is an operator which would execute
the method indicated at left but then return back the reference
to the now modified object. This is given in the desired() function
below. Since this object doesn't exist, it can't be demonstrated.
The filtered01 and filtered02 functions demonstrate trying to
put eval to work -- not crazy about that since it has the added
baggage of the globals(), locals() plus the need to write the calls
in string format.

Anyhow, just curious for ideas and sparking discussion.

def desired():
pass
# IF we had a --> operator which would execute the method at 
# left but return a ref to object
#return [8,9,7,1].sort()-->reverse()-->pop(0)--> # returns [8,7,1]
# return [8,9,7,1].sort()-->reverse()-->pop(0) # returns 9
# return [8,9,7,1].sort()-->reverse()-->pop(0) # equivalent to above

def filtered01():
popidx=0
return filter([8,9,7,1],'sort()','reverse()','pop(popidx)',locals=locals())

def filtered02():
return filter([8,9,7,1],'sort()','reverse()').pop(0)

def filter(obj,*args,**kwargs):
if 'globals' in kwargs:
globals_=kwargs['globals']
else:
globals_=globals()
if 'locals' in kwargs:
locals_ =kwargs['locals']
else:
locals_ =locals()
locals_.update(locals())
for methodCall in args:
eval('obj.%s'%methodCall,globals_,locals_)
return obj

print filtered01()  # returns [8, 7, 1]
print filtered02()  # returns 9

# LENGTH STACKUP (if all statements put on the same horizontal line)
# someFunc():
# a=[8,9,7,1]a.sort()a.reverse()a.pop(0)return a
# filtered01: 
# return filter([8,9,7,1],'sort()','reverse()','pop(0)',locals=locals())
# explicitReturn():
# a=[8,9,7,1].sort().reverse()a.pop(0)return a
# newFunc01:
# return [8,9,7,1]._('sort')._('reverse')._('pop',0)
# newFunc02:
# return [8,9,7,1].self_('sort').self_('reverse').self_('pop',0)
# desired:
# return [8,9,7,1]-->sort()-->reverse()-->pop(0)-->

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


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread dustin
On Sat, Feb 03, 2007 at 07:01:47PM +, Michael O\'Keefe wrote:
> Anyhow, just curious for ideas and sparking discussion.
...

I haven't been on the list long enough to know, but I would expect that this
idea and its relatives have been batted around at least once before.  I think a
lot of people have been frustrated at the repetitive nature of operations on
lists, for example, as you indicated in your first post.  I think there's room
for debate on whether specific list methods that currently return None should
instead return the list, although I would definitely consult the archives
before entering that fray. 

I expect that the idea of adding a new operator or any other syntactic change
is, like the count of 5, "right out".

For what it's worth, you can wrap an object so it behaves the way you like as
follows, although of course this will discard the return value of any functions
which produce one:

class wrapcall(object):
def __init__(self, inner): 
self.inner = inner 

def __getattr__(self, attr):
rv = getattr(self.inner, attr)
if callable(rv):
def wrap(*args, **kwargs):
rv(*args, **kwargs)
return self
return wrap
else:   
return rv

mylist = [1, 2, 3]
wrapcall(mylist).reverse().append(2).reverse()
assert mylist == [2, 1, 2, 3]

Dustin
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Eduardo \"EdCrypt\" O. Padoan
Cool! A way to write big one-liners and break the law of Demeter.
Also, this should be a Python-ideas, not a Python-dev Post.

-- 
EduardoOPadoan (eopadoan->altavix::com)
Bookmarks: http://del.icio.us/edcrypt
Blog: http://edcrypt.blogspot.com
Jabber: edcrypt at jabber dot org
ICQ: 161480283
GTalk: eduardo dot padoan at gmail dot com
MSN: eopadoan at altavix dot com
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] __dir__ and __all__

2007-02-03 Thread Giovanni Bajo
Hello,

I could not find a PEP for __dir__. I was thinking today that if __dir__ was 
added, I would find it useful if modules implemented it by returning __all__ 
(when __all__ is defined). Or even better, to return the same names that would 
be imported by a star-import (so, if __all__ is not defined, all names which 
do not start with '_').

This wouldn't prevent introspection tools to use mod.__dict__ to still access 
the module's global dictionary, of course. But it would allow module's authors 
to more clearly document the module's public API.
-- 
Giovanni Bajo

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


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Terry Reedy

<[EMAIL PROTECTED]> wrote in message 
news:[EMAIL PROTECTED]
| On Sat, Feb 03, 2007 at 07:01:47PM +, Michael O\'Keefe wrote:
| I haven't been on the list long enough to know, but I would expect that 
this
| idea and its relatives have been batted around at least once before.

Of course.

| I think a
| lot of people have been frustrated at the repetitive nature of operations 
on
| lists, for example, as you indicated in your first post.  I think there's 
room
| for debate on whether specific list methods that currently return None 
should
| instead return the list, although I would definitely consult the archives
| before entering that fray.

The current design of having mutation methods return None is Guido's 
explicit, intentional, conscious, and repeatedly affirmed design choice. 
He is convinced that the pain of repetition is worth the reduction of bugs 
that would happen when people forget that a list (self) -returning method 
also mutates.  I think comp.lang.python would be a better place for debate.

tjr



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


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Greg Ewing
Michael O'Keefe wrote:
> I'd like to see a built-in shorthand to allow me to 
> chain method calls even when a method call does not explicity 
> return a reference to the instance of the object (self).

> def newFunc02():
> return NewList([8,9,7,1]).self_('sort').self_('reverse').self_('pop',0)

My thought is that you're trying to write programs
in some other language using Python.

If you really want all that on one line, you can
do it already:

   x = NewList([8,9,7,1]); x.sort(); x.reverse(); return x.pop(0)

which is just as compact and doesn't suffer from
the weirdness of passing method names in as quoted
strings.

--
Greg
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Greg Ewing
[EMAIL PROTECTED] wrote:
> I think there's room
> for debate on whether specific list methods that currently return None should
> instead return the list, although I would definitely consult the archives
> before entering that fray.

Indeed. It's been discussed many times before.

It was a deliberate decision to have those methods
return None, because it makes it clear that they
operate in-place. I doubt that Guido's thinking
on that has changed at all.

--
Greg
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Michael Foord
Greg Ewing wrote:
> Michael O'Keefe wrote:
>   
>> I'd like to see a built-in shorthand to allow me to 
>> chain method calls even when a method call does not explicity 
>> return a reference to the instance of the object (self).
>> 
>
>   
>> def newFunc02():
>> return NewList([8,9,7,1]).self_('sort').self_('reverse').self_('pop',0)
>> 
>
> My thought is that you're trying to write programs
> in some other language using Python.
>
> If you really want all that on one line, you can
> do it already:
>
>x = NewList([8,9,7,1]); x.sort(); x.reverse(); return x.pop(0)
>
> which is just as compact and doesn't suffer from
> the weirdness of passing method names in as quoted
> strings.
>   
You could write a metaclass which decorates all methods in a class.  Any 
methods which return None could return self instead.

Michael

> --
> Greg
> ___
> Python-Dev mailing list
> [email protected]
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk
>
>
>   

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


Re: [Python-Dev] Shortcut Notation for Chaining Method Calls

2007-02-03 Thread Nick Coghlan
Michael O'Keefe wrote:
> I'm sure there are other ways to do this as well but what do people
> think? Has something like this come up before?

Yes, this has come up before, and list.sort and list.reverse were 
identified as the methods people were most likely to want to chain. The 
sorted() and reversed() builtins were the result.

Also, the spelling you propose creates a horrible confusion when calling 
a method which already has a real return value (like list.pop).

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
 http://www.boredomandlaziness.org
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com