Mailing List Archive

1 2 3  View All
Re: LOAD_NAME & classes [ In reply to ]
[Steve Holden]
> So, the problem is the implicit local declaration that assumed when
> the compiler detects a binding lower down the function's code than
> the first reference to it, coupled with their function-wide
> scope. It is compounded by the fact that although the analysis is
> performed at compile time the error is only reported at run time.

Well put.

> Might it make more sense to issue a warning at compile time to the
> effect that a variable is being used before it's assigned?

Yes. Historically (when LOAD_FAST was added) we didn't have a
framework for compile-time warnings, but now we do.

> How completely are (re)bindings detected by the static analysis? Can
> you necessarily guarantee that a LOAD_FAST is always looking at a
> local name? [.You'll understand I'm not familiar with the details of
> code generation].

Yes, LOAD_FAST is only emitted if the compiler has decided that it's
a local name, and then there's no exception (though that is exactly
what I contemplated changing earlier in this thread).

> Seems to me the real problem here is explaining (by the
> interpreter's behavior, rather than in the documentation ;-) the
> scope of locals and how a name is determined to be local. It might
> help beginners if there was some really easy way to get a fuller
> explanation of an error message. Not sure how best that could be
> retrofitted, but it's better than code breakage.

I think if they look up UnboundLocalError in the docs they find the
right clues. Of course it's not necessarily easy to find that bit of
documentation (though Google's first hit is very helpful).

> Unfortunately the scoping rules are now "in the wild", so it's not
> possible to change things too radically without mucho pain for those
> who have already relied on them.

Changing LOAD_FAST so that

x = 1
def f():
print x
x = 2
print x

prints 1 followed by 2 instead of raising UnboundLocalError would not
break existing code (except code relying on specific exceptions to be
raised -- but such code is always exempt from non-breakage
guarantees).

--Guido van Rossum (home page: http://www.python.org/~guido/)
Re: LOAD_NAME & classes [ In reply to ]
> > Might it make more sense to issue a warning at compile time to the effect
> > that a variable is being used before it's assigned? How completely are
>
> Hard to make sure, so, it would always be "MIGHT be used before
> assignment". E.g.,
>
> def f():
> for i in range(6):
> if i>0: print x,
> x = str(i)
>
> this is OK... no UnboundNameError. Now, change the if's guard to
> if SolveTuringHaltingProblem(i): print x,
> to see why it's hard to make sure about this at compile time.
>
> A warning might still be OK of course, even though it may need to
> be worded in wishy-washy "might" terms -- this IS peculiar usage.

GCC warns about this stuff as soon as there's a path through the code
that could leave a variable unassigned, even if the path may not be
reachable depending on what other functions do, and while it
occasionally caused my to insert a useless initialization, I've
usually found that it was hard enough to prove to myself that the
initialization was unneeded to make me happy to insert it.

--Guido van Rossum (home page: http://www.python.org/~guido/)
RE: LOAD_NAME & classes [ In reply to ]
[Guido]
> ...
> No; apart from you, most people were happy with the rule "nested
> functions don't work".

Most, yes, but most people are happy with UnboundLocalError too. The
business about nested functions not being able to see each other was a FAQ
regardless, and Aaron Watters wrote the FAQ Wizard blurb about it. This FAQ
entry was distinct from the FAQ entry about nested functions not being able
to see the locals in enclosing functions, despite that they were really the
same issue, because people who understood the latter just didn't see the
connection to the former without additional words.

So the answer to my original question:

(perhaps you've forgotten how many times you had to explain that one,
and how difficult it was to get across?).

is either "yes", or "no, but I eventually left such explaining to others,
and so have nothing to forget" <wink>.
Re: LOAD_NAME & classes [ In reply to ]
>>>>> "GvR" == Guido van Rossum <guido@python.org> writes:

GvR> Changing LOAD_FAST so that

GvR> x = 1
GvR> def f():
GvR> print x
GvR> x = 2
GvR> print x

GvR> prints 1 followed by 2 instead of raising UnboundLocalError
GvR> would not break existing code (except code relying on specific
GvR> exceptions to be raised -- but such code is always exempt from
GvR> non-breakage guarantees).

It wouldn't break existing code, but it would encourage the existence
of broken code. It's asking for trouble to write a function that uses
a local and a global with the same name. I don't think we should bend
the rules to accommodate this kind of confusion.

Jeremy
RE: LOAD_NAME & classes [ In reply to ]
[Guido van Rossum]
> Why is the fact that this works:
>
> x = 12
> def f():
> print x
>
> a "fortunate" side effect? That's how the language works!

Yes. I got a fresh cup of coffee and smashed my head against a wall and now
my mental processes appear to be working again. At least, there's more
squeaking and rattling. My previous choice of words now appears to be
rather... unfortunate. <wink>

> I think you've got it backwards. My complaint is that if f() above
> eventually grew 150 lines of unrelated code ending with an unrelated
> assignment to a local variable x, the breakage would show up at an
> unexpected point. Except for this one, it's hard to make a change at
> the *tail* of a function that breaks something at the beginning!

Yes, I don't know what I was thinking. Maybe I need a donut. Thanks.

---
Patrick K. O'Brien
Orbtech
RE: LOAD_NAME & classes [ In reply to ]
[Michael Hudson, on UnboundLocalErrors]
> ...
> Wouldn't it be nice if these were flagged at compile time! More work
> for Jeremy <wink>.

As will (or already has <wink>) been pointed out, the compiler can only
guess, and can't always guess right (it could err on the side of bothering
you without cause, though). PyChecker goes a long way already. Java has a
mass of "definite assignment" rules instead, which in effect decree that you
must write code in such a way that the compiler can always guess right.
RE: LOAD_NAME & classes [ In reply to ]
[Guido]
> ...
> But Python *is* unique in that it doesn't require declarations. (I've
> got to admit that the Perl example saddened me. But then in Perl,
> local variables are a recent invention. :-)

Just FYI, "local()" in Perl is very old, and has always used dynamic scoping
rules. If you don't wrap local() around a vrbl decl, you get a global vrbl
instead, and that's also very old. What's relatively new is the "my()" vrbl
wrapper, which asks for a lexically scoped vrbl. What's very new is
"our()", which I still haven't figured out:

An "our" declares the listed variables to be valid globals within
the enclosing block, file, or eval. That is, it has the same scoping
rules as a "my" declaration, but does not create a local variable. If
more than one value is listed, the list must be placed in parentheses.
The our declaration has no semantic effect unless "use strict vars"
is in effect, in which case it lets you use the declared global
variable without qualifying it with a package name. (But only within
the lexical scope of the our declaration. In this it differs from
"use vars", which is package scoped.)

Anyone want to make a motion that we not ape Perl's scoping rules <wink>?
Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23, 2002, Guido van Rossum wrote:
>
> Changing LOAD_FAST so that
>
> x = 1
> def f():
> print x
> x = 2
> print x
>
> prints 1 followed by 2 instead of raising UnboundLocalError would not
> break existing code (except code relying on specific exceptions to be
> raised -- but such code is always exempt from non-breakage
> guarantees).

-1

I agree with Jeremy that such code is by definition broken because it
mixes global and local usage of the same variable within the same scope.
That's a nightmare for visual inspection.

BTW, the indentation came out bizarrely because you used a TAB char for
indentation. Naughty, naughty.
--
Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/

What if there were no rhetorical questions?
Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23 @ 12:43, Tim Peters wrote:
> Just FYI, "local()" in Perl is very old, and has always used dynamic scoping
> rules. If you don't wrap local() around a vrbl decl, you get a global vrbl
> instead, and that's also very old. What's relatively new is the "my()" vrbl
> wrapper, which asks for a lexically scoped vrbl. What's very new is
> "our()", which I still haven't figured out:
>
> An "our" declares the listed variables to be valid globals within
> the enclosing block, file, or eval. That is, it has the same scoping
> rules as a "my" declaration, but does not create a local variable. If
> more than one value is listed, the list must be placed in parentheses.
> The our declaration has no semantic effect unless "use strict vars"
> is in effect, in which case it lets you use the declared global
> variable without qualifying it with a package name. (But only within
> the lexical scope of the our declaration. In this it differs from
> "use vars", which is package scoped.)
>
> Anyone want to make a motion that we not ape Perl's scoping rules <wink>?

The our is akin to declaring something static in C. Except in
Perl, it can apply to an enclosure as well since you can build funcs
dynamically. Yay. I think python's scoping rules work just fine :)

Has there ever been a discussion about some easy or straight-forward
way of sharing a global instance across modules? For example, in a
gui app, you might want to structure the program such that there's a
global instance app (main.app) of the application that other modules
might want to query. I was never to happy with importing main and then
using main.app... I felt like I wanted to qualify it as a global, like:

from main import global app

-- Mike

--
Michael Gilfix
mgilfix@eecs.tufts.edu

For my gpg public key:
http://www.eecs.tufts.edu/~mgilfix/contact.html
Re: LOAD_NAME & classes [ In reply to ]
[Guido van Rossum]

> But Python *is* unique in that it doesn't require declarations. (I've
> got to admit that the Perl example saddened me. But then in Perl,
> local variables are a recent invention. :-)

Guido, I miss the point of the second sentence. Why were you saddened?
Don't you prefer _not_ having to declare locals, as Python does now?

--
François Pinard http://www.iro.umontreal.ca/~pinard
Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23, 2002, Michael Gilfix wrote:
>
> Has there ever been a discussion about some easy or straight-forward
> way of sharing a global instance across modules? For example, in a
> gui app, you might want to structure the program such that there's a
> global instance app (main.app) of the application that other modules
> might want to query. I was never to happy with importing main and then
> using main.app... I felt like I wanted to qualify it as a global, like:
>
> from main import global app

The simple way to do it, IMO, is to import a joint module, called
something like cfg. I just did a little hack in a script with

cfg = imp.new_module('cfg')

but I don't know how well that works across modules. I think you'd need
to poke it into sys.modules in order for it to be shared, but I haven't
tested it.
--
Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/

What if there were no rhetorical questions?
Re: LOAD_NAME & classes [ In reply to ]
> [Guido van Rossum]
> > But Python *is* unique in that it doesn't require declarations. (I've
> > got to admit that the Perl example saddened me. But then in Perl,
> > local variables are a recent invention. :-)
>
> Guido, I miss the point of the second sentence. Why were you saddened?
> Don't you prefer _not_ having to declare locals, as Python does now?
>
> François Pinard http://www.iro.umontreal.ca/~pinard

François, I was sad because Perl seemed to use dynamic scoping when
you declare a local variable. Tim has since explained that Perl's
local is in fact ancient. I'm also sad that Perl doesn't default to
locals, but that's not my problem.

--Guido van Rossum (home page: http://www.python.org/~guido/)
Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23 @ 14:13, Aahz wrote:
> On Tue, Apr 23, 2002, Michael Gilfix wrote:
> >
> > Has there ever been a discussion about some easy or straight-forward
> > way of sharing a global instance across modules? For example, in a
> > gui app, you might want to structure the program such that there's a
> > global instance app (main.app) of the application that other modules
> > might want to query. I was never to happy with importing main and then
> > using main.app... I felt like I wanted to qualify it as a global, like:
> >
> > from main import global app
>
> The simple way to do it, IMO, is to import a joint module, called
> something like cfg. I just did a little hack in a script with
>
> cfg = imp.new_module('cfg')
>
> but I don't know how well that works across modules. I think you'd need
> to poke it into sys.modules in order for it to be shared, but I haven't
> tested it.

Yeah, that's another good way to do it. Have some sort of
configuration object you could query. It would be nice if python
offered a facility for sharing pooled data: maybe a global
configuration object? That way it's more explicit. It could also
remove some redundant code that I tend to put in many applications.

import config

my_opt = config.get_opt ('mymodule')
# Set a new global opt
config.set_opt ('attrib') = blah

Maybe even provide some hooks for populating the config object.

-- Mike

--
Michael Gilfix
mgilfix@eecs.tufts.edu

For my gpg public key:
http://www.eecs.tufts.edu/~mgilfix/contact.html
Re: LOAD_NAME & classes [ In reply to ]
[Guido van Rossum]

> I was sad because Perl seemed to use dynamic scoping when you declare a
> local variable. Tim has since explained that Perl's local is in fact
> ancient. I'm also sad that Perl doesn't default to locals, but that's
> not my problem.

Agreed.

I've been using Perl since Perl 1, all the way to Perl 5. When the `local()'
declaration appeared, probably around Perl 2 or Perl 3 (I do not remember), I
started using it everywhere in an effort of protecting each procedure against
each other. It was also a convenient way to give names to formal arguments,
through "local(name1, name2, ...) = @_" as the first statement in a `sub'.

When "my(LIST)" appeared, one or two major releases later, I progressively
converted all my programs to use it, as it is more in the spirit of what
I wanted. The overall impression that was left to me is that a lot of
declarations are needed, anyway, if you consistently aim clean Perl scripts.

So, there is now an "our(...)" declaration in Perl? Hopefully, it will
not miss me much! :-) And who remembers the "own" specifier of Algol-60? :-)

--
François Pinard http://www.iro.umontreal.ca/~pinard
Re: LOAD_NAME & classes [ In reply to ]
[Michael Gilfix]

> It would be nice if python offered a facility for sharing pooled data:
> maybe a global configuration object? That way it's more explicit.
> It could also remove some redundant code that I tend to put in many
> applications.

> import config

> my_opt = config.get_opt ('mymodule')
> # Set a new global opt
> config.set_opt ('attrib') = blah

> Maybe even provide some hooks for populating the config object.

I already use `config' (that precise identifier) a lot in my things,
so please do not even _think_ using it for something else! :-) :-)

For small projects, such a thing might be overkill. For big projects,
there are a few (maybe many) avenues and ways how to achieve this sharing,
and I'm glad having the freedom of installing subtle nuances between
projects, as needed. That is, I would fear a bit being pulled in an
arbitrary direction: it would have to be convincingly damned good. :-)

Better, maybe, would be to merely document some of the possible avenues.
Most of these require only a tiny investment in lines of code anyway.

--
François Pinard http://www.iro.umontreal.ca/~pinard
Re: Re: LOAD_NAME & classes [ In reply to ]
Upon futher reflection, I would agree with you. It's something I
find slightly confusing when I first started with python - what the
best method sharing a global instance is. I agree any such mechanism
needs to be well thought out though. Perhaps some good documentation
is the best solution.

-- Mike

On Tue, Apr 23 @ 15:49, François Pinard wrote:
> I already use `config' (that precise identifier) a lot in my things,
> so please do not even _think_ using it for something else! :-) :-)
>
> For small projects, such a thing might be overkill. For big projects,
> there are a few (maybe many) avenues and ways how to achieve this sharing,
> and I'm glad having the freedom of installing subtle nuances between
> projects, as needed. That is, I would fear a bit being pulled in an
> arbitrary direction: it would have to be convincingly damned good. :-)
>
> Better, maybe, would be to merely document some of the possible avenues.
> Most of these require only a tiny investment in lines of code anyway.

--
Michael Gilfix
mgilfix@eecs.tufts.edu

For my gpg public key:
http://www.eecs.tufts.edu/~mgilfix/contact.html
Re: Re: LOAD_NAME & classes [ In reply to ]
michael wrote:


> Upon futher reflection, I would agree with you. It's something I
> find slightly confusing when I first started with python - what the
> best method sharing a global instance is. I agree any such mechanism
> needs to be well thought out though. Perhaps some good documentation
> is the best solution.

http://www.python.org/doc/current/tut/node8.html#SECTION008100000000000000000

</F>
Re: Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23, 2002, Fredrik Lundh wrote:
> michael wrote:
>>
>> Upon futher reflection, I would agree with you. It's something I
>> find slightly confusing when I first started with python - what the
>> best method sharing a global instance is. I agree any such mechanism
>> needs to be well thought out though. Perhaps some good documentation
>> is the best solution.
>
> http://www.python.org/doc/current/tut/node8.html#SECTION008100000000000000000

That addresses the technical mechanism, but not the use case at hand.
--
Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/

What if there were no rhetorical questions?
Re: Re: LOAD_NAME & classes [ In reply to ]
Aahz wrote:

> > http://www.python.org/doc/current/tut/node8.html#SECTION008100000000000000000
>
> That addresses the technical mechanism, but not the use case at hand.

the use case was "some easy or straight-forward way of
sharing a global instance across modules".

the answer is "put it in a module".

end of story.

followups to comp.lang.python, thank you.

</F>
Re: Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23, 2002, Fredrik Lundh wrote:
> Aahz wrote:
>
>>> http://www.python.org/doc/current/tut/node8.html#SECTION008100000000000000000
>>
>> That addresses the technical mechanism, but not the use case at hand.
>
> the use case was "some easy or straight-forward way of
> sharing a global instance across modules".
>
> the answer is "put it in a module".
> end of story.

That's what I said earlier. But where is this documented? Never mind,
I just submitted a FAQ entry, 4.105.
--
Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/

What if there were no rhetorical questions?
Re: Re: LOAD_NAME & classes [ In reply to ]
> That's what I said earlier. But where is this documented?

I'm not sure that every possible handy coding tip deserves to be in
the documentation. There ought to be (and are!) plenty of other
introductory texts that can serve this purpose.

Also, in this particular case, the question ("how do I share data
between modules") and the answer ("put it in a module and import it")
seems pretty obvious once you have a decent grip of module semantics.

--Guido van Rossum (home page: http://www.python.org/~guido/)
Re: Re: LOAD_NAME & classes [ In reply to ]
On Tue, Apr 23, 2002, Guido van Rossum wrote:
>Aahz:
>>
>> That's what I said earlier. But where is this documented?
>
> Also, in this particular case, the question ("how do I share data
> between modules") and the answer ("put it in a module and import it")
> seems pretty obvious once you have a decent grip of module semantics.

Maybe. I personally agree. But I've seen too many people on c.l.py who
appear to be definitely past the newbie level miss the boat on this
topic. We'll see whether the FAQ entry helps; it should be sufficient.
I noted in the FAQ entry that importing a module is also the Pythonic
answer to the Singleton design pattern, so people searching for
Singleton should find that.
--
Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/

What if there were no rhetorical questions?
RE: Re: LOAD_NAME & classes [ In reply to ]
[Aahz]
> Maybe. I personally agree. But I've seen too many people on c.l.py who
> appear to be definitely past the newbie level miss the boat on this
> topic. We'll see whether the FAQ entry helps; it should be sufficient.
> I noted in the FAQ entry that importing a module is also the Pythonic
> answer to the Singleton design pattern, so people searching for
> Singleton should find that.

Send them to Alex's article: http://www.aleax.it/5ep.html

---
Patrick K. O'Brien
Orbtech
Re: Re: LOAD_NAME & classes [ In reply to ]
On Wednesday 24 April 2002 00:04, Patrick K. O'Brien wrote:
> [Aahz]
>
> > I noted in the FAQ entry that importing a module is also the Pythonic
> > answer to the Singleton design pattern, so people searching for
> > Singleton should find that.
>
> Send them to Alex's article: http://www.aleax.it/5ep.html

Using a module is a better answer over 90% of the time. Most people think
of Singleton "by reflex" when they believe "there's gonna be only one of
these", rather than when they really need to solve the forces covered in
the Gof4's Singleton DP, first and foremost subclassability.


Alex
Re: LOAD_NAME & classes [ In reply to ]
Guido:

> def f():
> print x # user thinks this should print the global
> # 2000 lines of unrelated code
> for x in "some sequence": # doesn't realize this overrides x
> do_something_with(x)

Perhaps a warning could be issued if the first reference
to a local textually precedes the first assignment to it?
Would that help catch things like this, without complaining
about too much existing code?

Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury, | A citizen of NewZealandCorp, a |
Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. |
greg@cosc.canterbury.ac.nz +--------------------------------------+

1 2 3  View All