Bengt Richter wrote:
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

Reply via email to