B
Brian Sabbey
Here is a pre-PEP for what I call "suite-based keyword arguments". The
mechanism described here is intended to act as a complement to thunks.
Please let me know what you think.
Suite-Based Keyword Arguments
-----------------------------
Passing complicated arguments to functions is currently awkward in Python.
For example, the typical way to define a class property winds up polluting
the class's namespace with the property's get/set methods. By allowing
keyword arguments to be defined in a suite following a function call,
complicated arguments can be passed in a cleaner, easier way.
Examples
========
Using suite-based keyword arguments, the code
f(x = 1)
is equivalent to
f():
x = 1
In general, a suite following a function call creates a new scope. The
bindings created in this scope get passed to the function as keyword
arguments.
Suite-based keyword arguments can be mixed with regular arguments:
f(1, 2, y = 4):
x = 1
Motivation
==========
One motivation for suite-based keywords is to allow cleaner definitions of
properties. Currently, properties are typically define as in this
example:
class C(object):
def getx(self):
return self.__x
def setx(self, value):
self.__x = value
def delx(self):
del self.__x
x = property(getx, setx, delx, "I'm the 'x' property.")
The 'getx', 'setx', and 'delx' methods get defined in the namespace of the
class even though one wants only to pass them to 'property'. Ideally, one
would want these methods to be defined in their own namespace. Also, it
would be helpful when reading the code if the layout of the code gave
visual indication that their only purpose is to be used in a property.
Using suite-based keyword arguments, and without any changes to the
'property' type, this code can be written as:
class C(object):
x = property():
doc = "I'm the 'x' property."
def fget(self):
return self.__x
def fset(self, value):
self.__x = value
def fdel(self):
del self.__x
Here, 'fget', 'fset' and 'fdel' do not wind up as methods of the class,
and it is visually clear that they are methods only for the 'x' property.
Also, this code is less bug-prone since the name of each method need
appear only once.
Passing callbacks in other situations is made similarly easier and
cleaner:
setHandlers():
def success():
print 'success'
def failure():
print 'an error has occured'
def apocalypse():
print 'a serious error has occured'
a = [1,3,2]
a.sort():
def cmpfunc(x,y):
return cmp(x,y)
Situations that do not require callbacks can also be better organized
using suite-based keywords. For example, here is code as it would
currently be written in Python:
if a:
x = 1
else:
x = 2
f(x=x)
When reading this code, one reaches the 'if' statment without knowing what
its purpose is-- layout of the code does not indicate that the 'if'
statement is calculating an argument to 'f'. Also, it requires a binding
that serves no purpose other than to hold an argument to 'f', yet this
binding persists for the rest of the surrounding function.
Here is the same code using suite-based keyword arguments
f():
if a:
x = 1
else:
x = 2
When reading this code, it is easy to skip over everything that is
involved in calling 'f', if one so desires. Since the suite has its own
namespace, one does not have to worry that the suite creates some bindings
that will be important later in the function.
mechanism described here is intended to act as a complement to thunks.
Please let me know what you think.
Suite-Based Keyword Arguments
-----------------------------
Passing complicated arguments to functions is currently awkward in Python.
For example, the typical way to define a class property winds up polluting
the class's namespace with the property's get/set methods. By allowing
keyword arguments to be defined in a suite following a function call,
complicated arguments can be passed in a cleaner, easier way.
Examples
========
Using suite-based keyword arguments, the code
f(x = 1)
is equivalent to
f():
x = 1
In general, a suite following a function call creates a new scope. The
bindings created in this scope get passed to the function as keyword
arguments.
Suite-based keyword arguments can be mixed with regular arguments:
f(1, 2, y = 4):
x = 1
Motivation
==========
One motivation for suite-based keywords is to allow cleaner definitions of
properties. Currently, properties are typically define as in this
example:
class C(object):
def getx(self):
return self.__x
def setx(self, value):
self.__x = value
def delx(self):
del self.__x
x = property(getx, setx, delx, "I'm the 'x' property.")
The 'getx', 'setx', and 'delx' methods get defined in the namespace of the
class even though one wants only to pass them to 'property'. Ideally, one
would want these methods to be defined in their own namespace. Also, it
would be helpful when reading the code if the layout of the code gave
visual indication that their only purpose is to be used in a property.
Using suite-based keyword arguments, and without any changes to the
'property' type, this code can be written as:
class C(object):
x = property():
doc = "I'm the 'x' property."
def fget(self):
return self.__x
def fset(self, value):
self.__x = value
def fdel(self):
del self.__x
Here, 'fget', 'fset' and 'fdel' do not wind up as methods of the class,
and it is visually clear that they are methods only for the 'x' property.
Also, this code is less bug-prone since the name of each method need
appear only once.
Passing callbacks in other situations is made similarly easier and
cleaner:
setHandlers():
def success():
print 'success'
def failure():
print 'an error has occured'
def apocalypse():
print 'a serious error has occured'
a = [1,3,2]
a.sort():
def cmpfunc(x,y):
return cmp(x,y)
Situations that do not require callbacks can also be better organized
using suite-based keywords. For example, here is code as it would
currently be written in Python:
if a:
x = 1
else:
x = 2
f(x=x)
When reading this code, one reaches the 'if' statment without knowing what
its purpose is-- layout of the code does not indicate that the 'if'
statement is calculating an argument to 'f'. Also, it requires a binding
that serves no purpose other than to hold an argument to 'f', yet this
binding persists for the rest of the surrounding function.
Here is the same code using suite-based keyword arguments
f():
if a:
x = 1
else:
x = 2
When reading this code, it is easy to skip over everything that is
involved in calling 'f', if one so desires. Since the suite has its own
namespace, one does not have to worry that the suite creates some bindings
that will be important later in the function.