[Python-ideas] 'Injecting' objects as function-local constants

Bruce Leban bruce at leapyear.org
Tue Jun 14 03:45:05 CEST 2011


It seems to me this discussion is mixing some different issues.

(1) having secret parameters that don't show in help().

(2) injecting a value in some way

I think these should be thought about separately.

*For secret parameters:* help() could have a convention that it doesn't
display variables with that start with _ or something like that, but that
might have compatibility issues. Alternatively, there could be some new
syntax or a decorator like

  >>> *@help.hide*("x,y")
  def foo(a, b, x=[], y={}): pass

  >>> help(foo)
  Help on function foo in module __main__:

  f(a, b)

*For injecting values:* There are several different cases. I'll use the
arbitrary keyword *special* in the snippets below (but note that the keyword
means something slightly different in each case):

  def foo1():
    x = *special *[]
    ...
    x.append(t)

Sets x every time the function is called to the same static list. What's
special here is that I have one list created that gets reused, not a new
list every time. This is how default arguments work and is useful for an
accumulating list.

  def foo2():
    *special *y = 0
    ...
    y += t

Initializes y once to 0 (at some time before the next line of code is
reached). This is how static works in C++. This is what I want if my
accumulating variable is a counter since numbers are immutable. This case
easily handles the first case. If you never rebind x, you don't need to do
anything special, otherwise something like this:

  def foo1a():
    *special *_x = []
    x = _x
    ... # might rebind x
    x.append(t)

It's a bit clumsy to use the first case to handle the second case:

  def foo2a():
    y = *special *[0]
    ...
    y[0] += t

In addition, there are other use cases being discussed. This creates a new
scope for i every time through the loop:

  def foo3():
    result = []
    for *special *i in range(10):
      def z(): return i
      result.append(z)

And this injects a mock to replace a library function:

  def foo4():
    return random.random()
  w = *special*(random.random=lambda: 0.1) foo4()

Just because we might use similar hacks to do these now, doesn't mean that
they are necessarily the same and I think the discussion has been going in
several different directions simultaneously. I think all these cases have
merits but I don't know which are more important. The last case seems to be
handled reasonably well by various mock libraries using with, so I'm not
particularly worried about it. I would like support for case 1 or 2. I don't
like the idea of using a different function argument hack instead of the
current one.

--- Bruce
Follow me: http://www.twitter.com/Vroo http://www.vroospeak.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20110613/9766a825/attachment.html>


More information about the Python-ideas mailing list