[Python-Dev] Shortcut Notation for Chaining Method Calls
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
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
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
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__
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
<[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
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
[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
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
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
