Re: Problem with Lexical Scope
- From: Duncan Booth <duncan.booth@xxxxxxxxxxxxxxx>
- Date: 12 Dec 2005 09:00:14 GMT
jslowery@xxxxxxxxx wrote:
> I am using python2.4 and the following code throws a "status variable"
> not found in the inner-most function, even when I try to "global" it.
>
> def collect(fields, reducer):
> def rule(record):
> status = True
> def _(x, y):
> cstat = reducer(x, y)
> if status and not cstat:
> status = False
> return y
> return reduce(_, [record[field] for field in fields])
> return rule
>
> What gives?
You rebind status in the inner function. Binding to a name makes it local
to that function (unless declared global). A name in an enclosing function
is neither local nor global so you cannot rebind it.
Ways round this include storing the status in a mutable value, making it an
attribute of a class, or rewriting the code to not require setting an outer
variable in the first place.
The last of these is the easiest in this case: status is never actually
used or returned anywhere so you could just remove all references to it
with no impact on the code. In fact, so long as reducer has no side
effects, you could just do this:
def collect(fields, reducer):
def rule(record):
if fields:
return record[fields[-1]]
return rule
Alternatively, if I assume you actually wanted rule to return the status as
well as y, then the outer assignment disappears quite easily:
def collect(fields, reducer):
def rule(record):
def _((x, status), y):
cstat = reducer(x, y)
return (y, status and cstat)
return reduce(_, [record[field] for field in fields], (0, True))
return rule
If reducer has no side effects this can be further reduced:
def collect(fields, reducer):
def rule(record):
def _((x, status), y):
return (y, status and reducer(x,y))
return reduce(_, [record[field] for field in fields], (0, True))
return rule
Given that the final y returned is simply the last record[field] maybe you
only wanted the status value? In that case expanding the reduce and _ into
inline code is likely to make things clearer:
def collect(fields, reducer):
def rule(record):
prev = 0
for field in fields:
if not reducer(prev, record[field]):
return False
prev = record[field]
return True
return rule
.
- Follow-Ups:
- Re: Problem with Lexical Scope
- From: jslowery@xxxxxxxxx
- Re: Problem with Lexical Scope
- References:
- Problem with Lexical Scope
- From: jslowery@xxxxxxxxx
- Problem with Lexical Scope
- Prev by Date: Re: lambda (and reduce) are valuable
- Next by Date: Re: mail attachment with non-ascii name
- Previous by thread: Re: Problem with Lexical Scope
- Next by thread: Re: Problem with Lexical Scope
- Index(es):
Relevant Pages
|