Where do nested functions live?
Frederic Rentsch
anthra.norell at vtxmail.ch
Sun Oct 29 04:16:45 EST 2006
Diez B. Roggisch wrote:
>> If I may turn the issue around, I could see a need for an inner function
>> to be able to access the variables of the outer function, the same way a
>> function can access globals. Why? Because inner functions serve to
>> de-multiply code segments one would otherwise need to repeat or to
>> provide a code segment with a name suggestive of its function. In either
>> case the code segment moved to the inner function loses contact with its
>> environment, which rather mitigates its benefit.
>>
>
> Maybe I'm dense here, but where is your point? Python has nested lexical
> scoping, and while some people complain about it's actual semantics, it
> works very well:
>
> def outer():
> outer_var = 10
> def inner():
> return outer_var * 20
> return inner
>
> print outer()()
>
>
>
> Diez
>
My point is that an inner function operating on existing outer variables
should be allowed to do so directly. Your example in its simplicity is
unproblematic. Let us consider a case where several outer variables need
to be changed:
weeks = days = hours = minutes = seconds = 0
mseconds = 0.0
(code)
# add interval in milliseconds
have_ms = ((((((((((weeks * 7) + days) * 24) + hours) * 60) +
minutes) * 60) + seconds) * 1000) + mseconds)
new_ms = have_ms + interval_ms
# reconvert
s = new_ms / 1000.0
s = int (s)
mseconds = new_ms - s * 1000
m, seconds = divmod (s, 60)
h, minutes = divmod (m, 60)
d, hours = divmod (h, 24)
weeks, days = divmod (d, 7)
(more code)
At some later point I need to increment my units some more and probably
will again a number of times. Clearly this has to go into a function. I
make it an inner function, because the scope of its service happens to
be local to the function in which it comes to live. It operates on
existing variables of what is now its containing function.
def increment_time (interval_ms):
have_ms = ((((((((((weeks * 7) + days) * 24) + hours) * 60) +
minutes) * 60) + seconds) * 1000) + mseconds)
new_ms = have_ms + interval_ms
# reconvert
s = new_ms / 1000.0
s = int (s)
ms -= s * 1000 # Was mseconds = new_ms - s * 1000
m, s = divmod (s, 60) # Was m, seconds = divmod (s, 60)
h, m = divmod (m, 60) # Was h, minutes = divmod (m, 60)
d, h = divmod (h, 24) # Was d, hours = divmod (h, 24)
w, d = divmod (d, 7) # Was weeks, days = divmod (d, 7)
return w, d, h, m, s, ms
Functionizing I must change the names of the outer variables. Assigning
to them would make them local, their outer namesakes would become
invisible and I'd have to pass them all as arguments. Simpler is
changing assignees names, retaining visibility and therefore not having
to pass arguments. In either case I have to return the result for
reassignment by the call.
weeks, days, hours, minutes, seconds, milliseconds = increment_time
(msec)
This is a little like a shop where the mechanics have to get their tools
and work pieces from the manager and hand them back to him when they're
done. The following two examples are illustrations of my point. They are
not proposals for 'improvement' of a language I would not presume to
improve.
def increment_time (interval_ms):
outer weeks, days, hours, minutes, seconds, mseconds # 'outer'
akin to 'global'
(...)
mseconds = new_ms - s * 1000 # Assignee remains outer
m, seconds = divmod (s, 60)
h, minutes = divmod (m, 60)
d, hours = divmod (h, 24)
weeks, days = divmod (d, 7) # No return necessary
The call would now be:
increment_time (msec) # No reassignment necessary
Hope this makes sense
Frederic
More information about the Python-list
mailing list