Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Re: Python becoming less Lisp-like

Reply
Thread Tools

Re: Python becoming less Lisp-like

 
 
Bengt Richter
Guest
Posts: n/a
 
      03-18-2005
On Fri, 18 Mar 2005 09:16:42 -0800, Jeff Shannon <> wrote:

>Antoon Pardon wrote:
>> Op 2005-03-16, Jeff Shannon schreef <>:
>>
>>>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
 
Reply With Quote
 
 
 
 
Antoon Pardon
Guest
Posts: n/a
 
      03-21-2005
Op 2005-03-18, Jeff Shannon schreef <>:
> Antoon Pardon wrote:
>> Op 2005-03-16, Jeff Shannon schreef <>:
>>
>>>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
>> print a
>>
>> And the result should be:
>>
>> 43
>> 42
>>

>
> I'd still say that the name binding rules are very consistent. The
> name lookup rules are a little different (as they *should* be for
> class/instance attributes),


Why should they?

> 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.


Which is the special case and which is the normal case is not
that important here. The fact is that they behave different,
so you can't claim it is very consistent.

I'm getting the impression that 'consistent' just means:
that is how python works, on this newsgroup.

> 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.


I find it odd that you start by saying you still find them very
consistent and here state there is a slight inconsistency.

It seems we mean different things with "very consistent"

--
Antoon Pardon
 
Reply With Quote
 
 
 
 
Antoon Pardon
Guest
Posts: n/a
 
      03-21-2005
Op 2005-03-18, Bengt Richter schreef <>:
>

[ ... ]
>
> 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.


Well you have my support for this. But I have the impression this
differs from the previous time you came up with a similar idea.
If IRC your previous proposal limited the search to the local
scope, making a := b equivallent to something like a; a = b.

I must say I like your current idea better.

--
Antoon Pardon
 
Reply With Quote
 
Jeff Shannon
Guest
Posts: n/a
 
      03-21-2005
Antoon Pardon wrote:
> Op 2005-03-18, Jeff Shannon schreef <>:
>
> I find it odd that you start by saying you still find them very
> consistent and here state there is a slight inconsistency.


I said that the way that binding a name on a class instance always
creates an instance attribute regardless of the presence of a
similarly-named class attribute is consistent with the way that name
binding works in any scope. This is true. Binding of a name within a
function-local scope works the same way -- bindings are always created
within the narrowest scope unless something is explicitly done to
force other behavior.

You pointed out a case in which class/instance attributes behave
slightly differently than local/global names do, and I agree with you
that there is a difference in behavior there. However, that
difference is in the way that bare names are resolved into
local/global references, and *not* in the way that name binding works.
The name binding rules are consistent; the inconsistency is in name
*lookups*, and is a case of strong optimization of the standard case
affecting the behavior of an unusual (and strongly discouraged) case.
There is a slight inconsistency in something *other* than what the
O.P. was complaining about being inconsistent; I'm recognizing that
inconsistency at the same time as I'm attempting to point out that the
other "inconsistency" really *is* consistent. (I'm also pointing out
that this name-lookup inconsistency is a good example of "practicality
beats purity", because the value of the optimization is, IMO, much
greater than the cost of the inconsistency.)

Jeff Shannon

 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      03-22-2005
Op 2005-03-21, Jeff Shannon schreef <>:
> Antoon Pardon wrote:
>> Op 2005-03-18, Jeff Shannon schreef <>:
>>
>> I find it odd that you start by saying you still find them very
>> consistent and here state there is a slight inconsistency.

>
> I said that the way that binding a name on a class instance always
> creates an instance attribute regardless of the presence of a
> similarly-named class attribute is consistent with the way that name
> binding works in any scope. This is true. Binding of a name within a
> function-local scope works the same way -- bindings are always created
> within the narrowest scope unless something is explicitly done to
> force other behavior.


But bindings in function scope happen earlier. There already
happens some kind of binding at call time. If it wouldn't
you wouldn't get an UnboundLocalError but just a NameError.
What seems to happen is that at call time all local variable
get prebound to somekind of illegal value and if they still have
this illegal value when you acces them, python raises the
UnboundLocalError

To have something consistent with that with instances and classes
would mean that the interpreter would find out what attributes could
possible be created and do the samekind of prebindind so that if you
accessed such an attribute you wouldn't get an AttributeError but
something like an UnboundAttributeError.

> You pointed out a case in which class/instance attributes behave
> slightly differently than local/global names do, and I agree with you
> that there is a difference in behavior there. However, that
> difference is in the way that bare names are resolved into
> local/global references, and *not* in the way that name binding works.


Well I don't agree. If name binding would work the same, I would
expect other exceptions.

> The name binding rules are consistent; the inconsistency is in name
> *lookups*,


I'm not convinced. The lookup can find out about such cases on
intermediate scopes. I doubt that the lookup knows at the start
at what level he is going to find the name. So either he keeps
the name of local variables of each function somewhere, to do
the special case if the variable is local on that level or the
name has to be prebound somehow.

> and is a case of strong optimization of the standard case
> affecting the behavior of an unusual (and strongly discouraged) case.


That only affects the behaviour of an unusual (and strongly discouraged)
case, doesn't make it consistent. It may be a good argument for choosing
to do it this way despite it being (slightly) inconsisten. It is not
an argument for it being consistent.

> There is a slight inconsistency in something *other* than what the
> O.P. was complaining about being inconsistent; I'm recognizing that
> inconsistency at the same time as I'm attempting to point out that the
> other "inconsistency" really *is* consistent. (I'm also pointing out
> that this name-lookup inconsistency is a good example of "practicality
> beats purity", because the value of the optimization is, IMO, much
> greater than the cost of the inconsistency.)


I'm not so sure, but I'm not going to argue this.

--
Antoon Pardon
 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      03-22-2005
Antoon Pardon wrote:
> Op 2005-03-21, Jeff Shannon schreef <>:
>
>>Antoon Pardon wrote:
>>
>>>Op 2005-03-18, Jeff Shannon schreef <>:
>>>
>>>I find it odd that you start by saying you still find them very
>>>consistent and here state there is a slight inconsistency.

>>
>>I said that the way that binding a name on a class instance always
>>creates an instance attribute regardless of the presence of a
>>similarly-named class attribute is consistent with the way that name
>>binding works in any scope. This is true. Binding of a name within a
>>function-local scope works the same way -- bindings are always created
>>within the narrowest scope unless something is explicitly done to
>>force other behavior.

>
>
> But bindings in function scope happen earlier. There already
> happens some kind of binding at call time. If it wouldn't
> you wouldn't get an UnboundLocalError but just a NameError.
> What seems to happen is that at call time all local variable
> get prebound to somekind of illegal value and if they still have
> this illegal value when you acces them, python raises the
> UnboundLocalError
>

They don't get pre-bound to some kind of illegal value. The parser
determines due to the presence in the function's code of an assignment
with that name as object - by STATIC analysis - that the name is local,
and therefore generates local references for it. It's the failure of a
local read that gives rise to the UnboundLocalError.

If you want to talk about this as a binding you can, I suppose. In
actual fact, though, it's the code object's co_names attribute that says
which names are to be regarded as local, as far as I understand it.

> To have something consistent with that with instances and classes
> would mean that the interpreter would find out what attributes could
> possible be created and do the samekind of prebindind so that if you
> accessed such an attribute you wouldn't get an AttributeError but
> something like an UnboundAttributeError.
>

You appear to be asking for a very explicit (and extremely ambitious)
type of optimization here.

>
>>You pointed out a case in which class/instance attributes behave
>>slightly differently than local/global names do, and I agree with you
>>that there is a difference in behavior there. However, that
>>difference is in the way that bare names are resolved into
>>local/global references, and *not* in the way that name binding works.

>
>
> Well I don't agree. If name binding would work the same, I would
> expect other exceptions.
>
>
>> The name binding rules are consistent; the inconsistency is in name
>>*lookups*,

>
>
> I'm not convinced. The lookup can find out about such cases on
> intermediate scopes. I doubt that the lookup knows at the start
> at what level he is going to find the name. So either he keeps
> the name of local variables of each function somewhere, to do
> the special case if the variable is local on that level or the
> name has to be prebound somehow.
>


>
>>and is a case of strong optimization of the standard case
>>affecting the behavior of an unusual (and strongly discouraged) case.

>
>
> That only affects the behaviour of an unusual (and strongly discouraged)
> case, doesn't make it consistent. It may be a good argument for choosing
> to do it this way despite it being (slightly) inconsisten. It is not
> an argument for it being consistent.
>
>
>> There is a slight inconsistency in something *other* than what the
>>O.P. was complaining about being inconsistent; I'm recognizing that
>>inconsistency at the same time as I'm attempting to point out that the
>>other "inconsistency" really *is* consistent. (I'm also pointing out
>>that this name-lookup inconsistency is a good example of "practicality
>>beats purity", because the value of the optimization is, IMO, much
>>greater than the cost of the inconsistency.)

>
>
> I'm not so sure, but I'm not going to argue this.
>

Great. I though you were going to start up with the snails again ...

regards
Steve
--
Meet the Python developers and your c.l.py favorites March 23-25
Come to PyCon DC 2005 http://www.pycon.org/
Steve Holden http://www.holdenweb.com/
 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      03-22-2005
Op 2005-03-22, Steve Holden schreef <>:
> Antoon Pardon wrote:
>> Op 2005-03-21, Jeff Shannon schreef <>:
>>
>>>Antoon Pardon wrote:
>>>
>>>>Op 2005-03-18, Jeff Shannon schreef <>:
>>>>
>>>>I find it odd that you start by saying you still find them very
>>>>consistent and here state there is a slight inconsistency.
>>>
>>>I said that the way that binding a name on a class instance always
>>>creates an instance attribute regardless of the presence of a
>>>similarly-named class attribute is consistent with the way that name
>>>binding works in any scope. This is true. Binding of a name within a
>>>function-local scope works the same way -- bindings are always created
>>>within the narrowest scope unless something is explicitly done to
>>>force other behavior.

>>
>>
>> But bindings in function scope happen earlier. There already
>> happens some kind of binding at call time. If it wouldn't
>> you wouldn't get an UnboundLocalError but just a NameError.
>> What seems to happen is that at call time all local variable
>> get prebound to somekind of illegal value and if they still have
>> this illegal value when you acces them, python raises the
>> UnboundLocalError
>>

> They don't get pre-bound to some kind of illegal value. The parser
> determines due to the presence in the function's code of an assignment
> with that name as object - by STATIC analysis - that the name is local,
> and therefore generates local references for it. It's the failure of a
> local read that gives rise to the UnboundLocalError.
>
> If you want to talk about this as a binding you can, I suppose. In
> actual fact, though, it's the code object's co_names attribute that says
> which names are to be regarded as local, as far as I understand it.


And does this code object know which non-local names are on an
intermediate level and which are global? If not it seems the
binding has to be more than just the code object's co_names attribute.

>> To have something consistent with that with instances and classes
>> would mean that the interpreter would find out what attributes could
>> possible be created and do the samekind of prebindind so that if you
>> accessed such an attribute you wouldn't get an AttributeError but
>> something like an UnboundAttributeError.
>>

> You appear to be asking for a very explicit (and extremely ambitious)
> type of optimization here.


You misunderstand. I don't ask for this. I just argue that this is
what should happen in order to make what happens in function scope
and what happens with attributes (more) consistent with each other.

What I was wondering, doesn't __slots__ do something like this?

--
Antoon Pardon
 
Reply With Quote
 
TLOlczyk
Guest
Posts: n/a
 
      03-22-2005
On 16 Mar 2005 06:37:45 -0500, Carl Shapiro <cshapiro+>
wrote:

>I have a virtually completed port of CMUCL to Win32. And, if I was
>not busy organizing a Lisp conference, it would be publicly available
>by now.


If it's the conference I think, then the deadline for papers was about
a week ago. I suspect that most of the other routine parts have been
taken care of leaving scheduling. IOW your time is freeing up.

OTOH it may just be wishful thinking on my part. Any idea how much
longer?





The reply-to email address is .
This is an address I ignore.
To reply via email, remove 2002 and change yahoo to
interaccess,

**
Thaddeus L. Olczyk, PhD

There is a difference between
*thinking* you know something,
and *knowing* you know something.
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      03-22-2005

"Antoon Pardon" <> wrote in message
news:...
> And does this code object know which non-local names are on an
> intermediate level and which are global?


Yes (from 2.2):
>>> import dis
>>> x = 1
>>> def f():

.... y = 2
.... def g():
.... z = 3
.... print x,y,z
.... return g
....
>>> dis.dis(f)

0 SET_LINENO 1

3 SET_LINENO 2
6 LOAD_CONST 1 (2)
9 STORE_DEREF 0 (y)

12 SET_LINENO 3
15 LOAD_CLOSURE 0 (y)
18 LOAD_CONST 2 (<code object g at 008BA060, file
"<stdin
>", line 3>)

21 MAKE_CLOSURE 0
24 STORE_FAST 1 (g)

27 SET_LINENO 6
30 LOAD_FAST 1 (g)
33 RETURN_VALUE
34 LOAD_CONST 0 (None)
37 RETURN_VALUE
>>> g = f()
>>> dis.dis(g)

0 SET_LINENO 3

3 SET_LINENO 4
6 LOAD_CONST 1 (3)
9 STORE_FAST 0 (z)

12 SET_LINENO 5
15 LOAD_GLOBAL 1 (x)
18 PRINT_ITEM
19 LOAD_DEREF 0 (y) # intermediate value
22 PRINT_ITEM
23 LOAD_FAST 0 (z)
26 PRINT_ITEM
27 PRINT_NEWLINE
28 LOAD_CONST 0 (None)
31 RETURN_VALUE

Terry J. Reedy



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
More Efficiency,More Benefit,Less Risk,Less Work! jiajia wu ASP .Net 0 10-01-2009 01:50 PM
More Efficiency,More Benefit,Less Risk,Less Work! 6668 Ruby 0 05-14-2009 12:33 AM
Re: Is c.l.py becoming less friendly? Terry Reedy Python 3 02-06-2009 09:11 AM
Is c.l.py becoming less friendly? mk Python 1 02-05-2009 04:22 PM
mozilla spam filter becoming less effective Dave - Dave.net.nz NZ Computing 1 08-22-2005 05:43 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57