Python becoming less Lisp-like
Bengt Richter
bokr at oz.net
Fri Mar 18 14:58:17 EST 2005
On Fri, 18 Mar 2005 09:16:42 -0800, Jeff Shannon <jeffshannon at gmail.com> wrote:
>Antoon Pardon wrote:
>> Op 2005-03-16, Jeff Shannon schreef <jeffshannon at gmail.com>:
>>
>>>Bruno Desthuilliers wrote:
>>>
>>>>- if x is a class attribute of class A and a is an instance of A,
>>>>a.x=anyvalue create a new instance attribute x instead of modifying A.x
>>>
>>>This is very consistent with the way that binding a name in any scope
>>>will shadow any bindings of that name in "higher" scopes. It is the
>>>same principle by which one is able to use the same name for a
>>>function-local variable that is used for a global variable, without
>>>destroying that global variable. [...]
>>
>> Not entirely. The equivallent is imposible in function scope.
>> If function scope would work exactly equivallent as the
>> above the following should work
>>
>> a = 42
>> def f():
>> a = a + 1
>> print a
f() # ;-)
>> print a
>>
>> And the result should be:
>>
>> 43
>> 42
>>
IIRC, in some past version that used to be the way it worked (if you don't forget to call f() ;-)
I think it is logical. I.e., the right hand side of a = a + 1
is logically evaluated first, so the status at that time should IMO
determine the meaning of "a" -- i.e., look for it in an outer scope.
Next comes the local assignment of "a" which should create a local name
binding, but the code for determining the assigned value should IMO
be the code for the "a + 1" with no local binding of "a" yet existing.
I don't know how much code would break to go back to that, but maybe
not so much, since it's not legal now:
>>> a = 42
>>> def f():
... a = a +1
... print a
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'a' referenced before assignment
>>> print a
42
BTW, I would like a re-assign or find-and-rebind operation spelled ":=" which would
make x := 123 mean look for x as if to read its value in a right hand side expression,
(except do not look into __builtins__) and wherever found, rebind to 123 -- and if not found,
raise an exception.
I think var := 'something' would be a useful substitute for the idiom of
var[0] = 'something' and be unambiguous.
":=" as an operator could combine like <op>= if desired, so we could write
var +:= some.long.expression[that].you('do')**not.want.to.type.twice
instead of
_ = some.long.expression[that].you('do')**not.want.to.type.twice
var +:= _ # meaning var := var + _
or such.
>
>I'd still say that the name binding rules are very consistent. The
They are consistent, but I have to say the function-body full lookahead to determine
local vs outer (not to mention normal function vs generator) jars my sensibilities.
>name lookup rules are a little different (as they *should* be for
>class/instance attributes), and that's why there's a different net
>effect (UnboundLocalError) as shown in your example. I'd say,
>however, that if there's a special case here it's with the
>function-local variables, not the class/instance attributes. It's the
>optimizations to the function-local namespace which prevent
>transparent re-binding of global names. And given that the
>function-local namespace is by far the most heavily used, and the
>relative utility (and wisdom) of using globals in this way, this is a
>case where the benefit of the special case is well worth the cost of
>its slight inconsistency.
The optimization argument goes away with x := something I think, since
the x search can be limited to looking in the lexical environment
exactly like looking for read-only outer scope names now, just with
different consequences for finding or not finding.
Regards,
Bengt Richter
More information about the Python-list
mailing list