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.