On Tue, 18 Jan 2005 17:38:20 -0700, Steven Bethard <[EMAIL PROTECTED]> wrote:
Bengt Richter wrote:
Which make me wonder what plans there are for providing a better mechanism than default arguments as a way of initializing local function variables. Nested def's to create a closure with initialized values is pretty crufty for that, IMO.
What about using a class? Associating functions with data is pretty much what they're for...
Maybe extending the default argument space with whatever comes after e.g. a triple star delimiter in the argument list, but which wouldn't be counted as part of the normal arguments? E.g.,
def foo(x, y=123, *args, **kw, *** i=1, deftime=time.ctime()): return x*y, kw.get('which_time')=='now' and time.ctime() or deftime
If what you want is to have i=1 and deftime=time.ctime() available within foo, you could do something like (untested):
class foo(object): def __init__(self): self.i = 1 self.deftime = time.ctime() def __call__(self, x, y=123, *args, **kwds): return x*y, (kw.get('which_time') == 'now' and time.ctime() or self.deftime) foo = foo()
Total: 8 lines, much irrelevant cruft.
Or if you don't like 'foo = foo()', you could probably abuse the __new__ method (also untested):
class foo(object): i = 1 deftime = time.ctime() def __new__(cls, x, y=123, *args, **kwds): return x*y, (kw.get('which_time') == 'now' and time.ctime() or self.deftime)
Total: 6 lines, newbie-unfriendly abuse of __new__ ;-)
I guess my point is that if you want attribute associated with the function, it's often easy enough to write a class instead...
vs. 2 easy lines with minimal irrelevant cruft ;-)
If you're really counting lines, you might compare with the more compact:
class foo(object):
def __init__(self):
self.i, self.deftime = 1, time.ctime()
def __call__(self):
return x*y, kw.get('which_time') == 'now' and time.ctime() or self.deftime
foo = foo()
and
class foo(object):
i, deftime = 1, time.ctime()
def __new__(cls, x, y=123, *args, **kwds):
return x*y, kw.get('which_time') == 'now' and time.ctime() or self.deftime
And probably what you want to compare is N lines (function only) versus N + 2 lines (using __new__) and N + 4 lines (using __call__). If N is more than 2 lines (which is probably true in most cases), the difference isn't so dramatic.
Using a class also has the advantage that, assuming one already knows how classes work (which any Python programmer who wants the kind of scoping you're talking about should) you don't have to learn how something new to be able to use it -- that is, *** -> bound locals that don't contribute to arguments but are listed in the same place as arguments.
If you really want locals that don't contribute to arguments, I'd be much happier with something like a decorator, e.g.[1]:
@with_consts(i=1, deftime=time.ctime()) def foo(x, y=123, *args, **kw): return x*y, kw.get('which_time')=='now' and time.ctime() or deftime
Then you don't have to mix parameter declarations with locals definitions.
Steve
[1] I have no idea how implementable such a decorator would be. I'd just like to see function constants declared separate from arguments since they mean such different things.
--
http://mail.python.org/mailman/listinfo/python-list