Easy questions from a python beginner

W

wheres pythonmonks

I'm an old Perl-hacker, and am trying to Dive in Python. I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1.  Why is it that I cannot use print in booleans??  e.g.:
I found a nice work-around using eval(compile(.....,"<string>","exec"))...
Seems ugly to this Perl Programmer -- certainly Python has something better?

2.  How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
 tuples, and numbers)

3.  Why might one want to store "strings" as "objects" in numpy
arrays?  (Maybe they wouldn't)?

4.  Is there a way for me to make some function-definitions explicitly
module-local?
(Actually related to Q3 below: Is there a way to create an anonymous scope?)

5. Is there a way for me to introduce a indention-scoped variables in python?
See for example: http://evanjones.ca/python-pitfall-scope.html

6.  Is there a Python Checker that enforces Strunk and White and is
bad English grammar anti-python?  (Only half joking)
http://www.python.org/dev/peps/pep-0008/

Thanks,
W
 
W

wheres pythonmonks

Thanks for your answers -- it is much appreciated.

On #1: I had very often used chained logic with both logging and
functional purposes in Perl, and wanted to duplicate this in Python.
"It reads like english" Using the print_ print wrapper works for me.

Follow-up:
Is there a way to define compile-time constants in python and have the
bytecode compiler optimize away expressions like:

if is_my_extra_debugging_on: print ...

when "is_my_extra_debugging" is set to false? I'd like to pay no
run-time penalty for such code when extra_debugging is disabled.

On #2: My point regarding the impossibility of writing the swap
function for ints is to explicitly understand that this isn't
possible, so as not to look for solutions along those lines when
trying to write python code.

On #3: Sorry this is confusing, but I was browsing some struct array
code from numpy, in which one of the columns contained strings, but
the type information, supplied in numpy.array's dtype argument,
specified the type as a an "object" not a string. Just wondering why
one would do that.

On #4: So there are some hacks, but not something as easy as "import
unimportable" or an @noexport decorator. The underscore works, so
does "del".

On #5: Nesting the function was actually what I was thinking of doing,
but alas, I cannot modify outer-scope variables within a function, and
of course, I don't want to use globals.

On #6: Always trying to improve my writing -- and I thought it was
cute that Guido tries to encourage this as well.


I am programmer who likes to scope off variables as much as possible
(I believe in minimal state).

The following is an example of what I am trying to protect against:
http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters

Will try to avoid namespace mangling until next week.

Thanks again,

W



wheres pythonmonks said:
I'm an old Perl-hacker, and am trying to Dive in Python.  I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1.  Why is it that I cannot use print in booleans??  e.g.:

I found a nice work-around using
eval(compile(.....,"<string>","exec"))... Seems ugly to this Perl
Programmer -- certainly Python has something better?

In Python 2.x print is a statement. If you really wanted you could do:

  True and sys.write("It is true!\n")

In Python 3 you can do this:

  True and print("It is true!")

though I can't think of any situations where this would be better that just
writing:

  if somecondition: print "whatever"
2.  How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??

Why use a function?

  x, y = y, x
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
 tuples, and numbers)

If you want to use perl's operators I suggest you use perl.
3.  Why might one want to store "strings" as "objects" in numpy
arrays?  (Maybe they wouldn't)?

Why would one want to write incomprehensible questions?
4.  Is there a way for me to make some function-definitions explicitly
module-local?
(Actually related to Q3 below: Is there a way to create an anonymous
scope?)

Not really.
5. Is there a way for me to introduce a indention-scoped variables in
python? See for example: http://evanjones.ca/python-pitfall-scope.html

No. The page you reference effectively says 'my brain is used to the way
Java works'. *My* brain is used to the way Python works. Who is to say
which is better?
6.  Is there a Python Checker that enforces Strunk and White and is
bad English grammar anti-python?  (Only half joking)
http://www.python.org/dev/peps/pep-0008/
pylint will do quite a good job of picking over your code. Most people
don't bother.
 
S

Stephen Hansen

Follow-up:
Is there a way to define compile-time constants in python and have the
bytecode compiler optimize away expressions like:

if is_my_extra_debugging_on: print ...

when "is_my_extra_debugging" is set to false? I'd like to pay no
run-time penalty for such code when extra_debugging is disabled.

Any code wrapped in a __debug__ guard is utterly ommitted if you run
Python with the -O option. That, and asserts go away.
On #2: My point regarding the impossibility of writing the swap
function for ints is to explicitly understand that this isn't
possible, so as not to look for solutions along those lines when
trying to write python code.

Its impossible because Python's calling and namespace semantics simply
don't work like that. There's no references in the traditional sense,
because there's no variables-- boxes that you put values in. There's
just concrete objects. Objects are passed into the function and given
new names; that those objects have names in the enclosing scope is
something you don't know, can't access, and can't manipulate.. even the
objects don't know what names they happen to be called.

Check out http://effbot.org/zone/call-by-object.htm
On #3: Sorry this is confusing, but I was browsing some struct array
code from numpy, in which one of the columns contained strings, but
the type information, supplied in numpy.array's dtype argument,
specified the type as a an "object" not a string. Just wondering why
one would do that.

Strings are objects.

I don't use numpy, btu I'd assume "object" would basically mean,
"anything can go here", as everything is an object.
On #5: Nesting the function was actually what I was thinking of doing,
but alas, I cannot modify outer-scope variables within a function, and
of course, I don't want to use globals.

You can modify outer-scope objects: if they are mutable. I.e., a
dictionary. What you can't do is modify outer *scopes*, the namespaces.
You can't re-bind a new/different object to a certain name in an outer
scope.
I am programmer who likes to scope off variables as much as possible
(I believe in minimal state).

That's a fine and nice goal. In Python your only real tool for this is
to break things up into more logical functions.

--

Stephen Hansen
... Also: Ixokai
... Mail: me+list/python (AT) ixokai (DOT) io
... Blog: http://meh.ixokai.io/


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)

iQEcBAEBAgAGBQJMOhToAAoJEKcbwptVWx/lqHsH/jj/xCQuJtAcTQk3oji2h44P
yVL3oGPpa1ShOJAvGXp7Kja4xOSZcy0AZpT2rb0rZJhCowDE2aDyaK5q/sDXxGGs
2saSDCgzfG3NUU46FE1xOX4uV8wKfO/pMvUtTxpA652JAiZD8c4Q/U1UAT6IO2Yy
LpTwi0Ijf1PZxO01Td5I5/O9ao09kKvhscSmtmBNDOwPd/6E8TT3wOi3DHufbyHw
/xTTdCl5S3sUot1SxnQD43+NCySiaukedqGcR8mxF3aCOT7v40/clQK0sNrpcUmX
sOdjQU7u8U8cYQBVSJXxyZBzU2TsEepCSj11L2PgMvBs/ElKRrrfGiYQo9S5Wp4=
=Nvnj
-----END PGP SIGNATURE-----
 
T

Thomas Jollans

Thanks for your answers -- it is much appreciated.

On #1: I had very often used chained logic with both logging and
functional purposes in Perl, and wanted to duplicate this in Python.
"It reads like english" Using the print_ print wrapper works for me.

Follow-up:
Is there a way to define compile-time constants in python and have the
bytecode compiler optimize away expressions like:

if is_my_extra_debugging_on: print ...

when "is_my_extra_debugging" is set to false? I'd like to pay no
run-time penalty for such code when extra_debugging is disabled.
no.

On #3: Sorry this is confusing, but I was browsing some struct array
code from numpy, in which one of the columns contained strings, but
the type information, supplied in numpy.array's dtype argument,
specified the type as a an "object" not a string. Just wondering why
one would do that.

No expert on numpy, but maybe storing object references is cheaper than
storing strings here ?
On #5: Nesting the function was actually what I was thinking of doing,
but alas, I cannot modify outer-scope variables within a function, and
of course, I don't want to use globals.

yes you can. Well, at least since whenever the "nonlocal" keyword was
introduced (recent, might be 3.x only)

Or you can wrap what you want to change in a dict or list.
I am programmer who likes to scope off variables as much as possible
(I believe in minimal state).

The following is an example of what I am trying to protect against:
http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters

On the other hand, python scoping and namespace rules, while they may be
different to those in other languages, are nice and simple.
Will try to avoid namespace mangling until next week.


Cheers

- Thomas
 
A

Alf P. Steinbach /Usenet

* Stephen Hansen, on 11.07.2010 21:00:
Any code wrapped in a __debug__ guard is utterly ommitted if you run
Python with the -O option. That, and asserts go away.


Its impossible because Python's calling and namespace semantics simply
don't work like that. There's no references in the traditional sense,
because there's no variables-- boxes that you put values in. There's
just concrete objects. Objects are passed into the function and given
new names; that those objects have names in the enclosing scope is
something you don't know, can't access, and can't manipulate.. even the
objects don't know what names they happen to be called.

Check out http://effbot.org/zone/call-by-object.htm

Oh, I wouldn't give that advice. It's meaningless mumbo-jumbo. Python works like
Java in this respect, that's all; neither Java nor Python support 'swap'.

Of course there are variables, that's why the docs call them variables.

We've had this discussion before and I know from that that it is a religious
issue with a small subset of the Python community, where reason, facts, logic
does not apply and is not even recognized as such. So be it. So I'm not out to
convince you or other of that sub-community, or trying to reason with you folks
on this issue (futile, and generates flames pretty fast), but I do not want
newbies brainwashed into that non-reasoning nonsense pure faith religion.

For what it's worth, I'm sure that the effbot.org author, whose pages are
otherwise quite technically meaningful & useful, in this case, after the flame
war with some Java folks, decided that technical accuracy just wasn't worth it.

So, I believe, he punted, which is an eminently rational choice when one's goals
require acceptance in a society dominated by a religious clique. And just as I'm
not out to engage you in any debate on this issue (futile), neither am I calling
you irrational. Perhaps your choice is the same as that author's.


Cheers,

- Alf
 
C

Carl Banks

I'm an old Perl-hacker, and am trying to Dive in Python.

Welcome to the light.

 I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1.  Why is it that I cannot use print in booleans??  e.g.:


I found a nice work-around using eval(compile(.....,"<string>","exec"))....
Seems ugly to this Perl Programmer -- certainly Python has something better?

I'll repeat other people's sentiments: if you drop nothing else from
your perl habits, drop this one.

2.  How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
 tuples, and numbers)

Can't do it, but you can get reference-like behavior if you don't mind
a level of indirection. For example:

def swap(x,y):
t = y[0]
y[0] = x[0]
x[0] = t

a = [1]
b = [2]
swap(a,b)

There's no reason to do this for a swap() function, as you've already
seen. But it is sometimes handy for other things. (This includes
certain idioms involving regualar expression that are common in Perl.
Perl uses some special semantics when performing regexp searches that
allow automatic binding of match results. Python doesn't, so in some
cases it's helpful to define an object you can mutate to store that
information.)

In the more general sense, Python functions and methods that mutate
the object they operate on are pretty common.

3.  Why might one want to store "strings" as "objects" in numpy
arrays?  (Maybe they wouldn't)?

numpy is a library designed mainly to store numerical data, with some
advanced slicing operations and other cool stuff like
multdimensionality.

Some people, however, want to use the cool slicing operations on
arrays of Python objects, so numpy has a storage mode for arbitrary
Python objects.

(If you're wondering why they use object instead of a character type,
it's because rows of such an array are fixed-length strings. Main
reason to use those is to interface with Fortran string arrays, or
maybe to simulate crossword puzzles or something.)

4.  Is there a way for me to make some function-definitions explicitly
module-local?
(Actually related to Q3 below: Is there a way to create an anonymous scope?)

No. The (loose) convention is to define local or private functions
with a leading underscore to label them as "intended for internal use
only".

5. Is there a way for me to introduce a indention-scoped variables in python?
See for example:http://evanjones.ca/python-pitfall-scope.html

Yes, define a nested function. In Python 2 it's limited since you
cannot rebind variables in the surrounding scope; that's possible in
Python 3, though.

6.  Is there a Python Checker that enforces Strunk and White and is
bad English grammar anti-python?  (Only half joking)http://www.python.org/dev/peps/pep-0008/

There's a few, PyChecker and PyLint get mentioned a lot. I used to
use them until I noticed that it never actually caught anything
(except stuff I didn't care about like using "id" as a variable name).


Carl Banks
 
C

Carl Banks

On #4:  So there are some hacks, but not something as easy as "import
unimportable" or an @noexport decorator.  The underscore works, so
does "del".

Careful. If you have a module that looks like this:


def foo():
bar()

def bar():
print "hello"

del bar # bar is an internal function


It won't work; foo will raise NameError on bar if you try that.
However, del is useful to clean up code you run at module import time,
for example:


squares = []
for i in xrange(101):
squares.append(i*i)
del i


Carl Banks
 
N

News123

Carl said:
I'm an old Perl-hacker, and am trying to Dive in Python.

Welcome to the light.

I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1. Why is it that I cannot use print in booleans?? e.g.:

I found a nice work-around using eval(compile(.....,"<string>","exec"))...
Seems ugly to this Perl Programmer -- certainly Python has something better?

I'll repeat other people's sentiments: if you drop nothing else from
your perl habits, drop this one.

2. How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
tuples, and numbers)

Can't do it, but you can get reference-like behavior if you don't mind
a level of indirection. For example:

def swap(x,y):
t = y[0]
y[0] = x[0]
x[0] = t

a = [1]
b = [2]
swap(a,b)

or
def swap[x,y]:
x[0],y[0] = y[0],x[0]
 
C

Chris Rebert

Carl said:
I'm an old Perl-hacker, and am trying to Dive in Python.

Welcome to the light.

 I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1.  Why is it that I cannot use print in booleans??  e.g.:

True and print "It is true!"
I found a nice work-around using eval(compile(.....,"<string>","exec"))....
Seems ugly to this Perl Programmer -- certainly Python has something better?

I'll repeat other people's sentiments: if you drop nothing else from
your perl habits, drop this one.

2.  How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
 tuples, and numbers)

Can't do it, but you can get reference-like behavior if you don't mind
a level of indirection.  For example:

def swap(x,y):
    t = y[0]
    y[0] = x[0]
    x[0] = t

a = [1]
b = [2]
swap(a,b)

or
def swap[x,y]:
   x[0],y[0] = y[0],x[0]
File "<stdin>", line 1
def swap[x,y]:
^
SyntaxError: invalid syntax

Cheers,
Chris
 
N

News123

Chris said:
Carl said:
On Jul 11, 10:48 am, wheres pythonmonks <[email protected]>
wrote:
I'm an old Perl-hacker, and am trying to Dive in Python.
Welcome to the light.


I have some
easy issues (Python 2.6)
which probably can be answered in two seconds:

1. Why is it that I cannot use print in booleans?? e.g.:

True and print "It is true!"
I found a nice work-around using eval(compile(.....,"<string>","exec"))...
Seems ugly to this Perl Programmer -- certainly Python has something better?
I'll repeat other people's sentiments: if you drop nothing else from
your perl habits, drop this one.


2. How can I write a function, "def swap(x,y):..." so that "x = 3; y
= 7; swap(x,y);" given x=7,y=3??
(I want to use Perl's Ref "\" operator, or C's &).
(And if I cannot do this [other than creating an Int class], is this
behavior limited to strings,
tuples, and numbers)
Can't do it, but you can get reference-like behavior if you don't mind
a level of indirection. For example:

def swap(x,y):
t = y[0]
y[0] = x[0]
x[0] = t

a = [1]
b = [2]
swap(a,b)
or
def swap[x,y]:
x[0],y[0] = y[0],x[0]
def swap[x,y]:
File "<stdin>", line 1
def swap[x,y]:
apologies:

I meant
def swap(x,y):
x[0],y[0] = y[0],x[0]

a = [1]
b = [2]
swap(a,b)
 
M

MRAB

Alf said:
* Stephen Hansen, on 11.07.2010 21:00:

Oh, I wouldn't give that advice. It's meaningless mumbo-jumbo. Python
works like Java in this respect, that's all; neither Java nor Python
support 'swap'.

Of course there are variables, that's why the docs call them variables.
In Java a variable is declared and exists even before the first
assignment to it. In Python a 'variable' isn't declared and won't exist
until the first 'assignment' to it.
 
A

Alf P. Steinbach /Usenet

* MRAB, on 12.07.2010 00:37:
In Java a variable is declared and exists even before the first
assignment to it. In Python a 'variable' isn't declared and won't exist
until the first 'assignment' to it.

That is a misconception.

In Python a variable is declared by having an assignment to it, which for a
local variable may be anywhere within a routine.

If such a variable is used before it's been assigned to, then you get an
uninitialized variable exception. Clearly the variable must exist in order for
the exception to refer to it (not to mention the exception occurring at all).

def foo():
print( blah )
blah = "this is both an assignment and a declaration causing it to exist"

foo()

Clearly when the exception is raised, referring to the variable, the variable
exists.

Contrary to your statement that is before the assignment.

However, as stated up-thread, I do not expect facts, logic or general reasoning
to have any effect whatsoever on such hard-core religious beliefs. And I do not
care whether I convince you or not. But I *do not* want the religious subset of
the community to succeed too much in propagating nonsense idiot beliefs to
newbies -- hence the concrete example that any newbie can try.


Cheers & hth.,

- Alf
 
S

Stephen Hansen

However, as stated up-thread, I do not expect facts, logic or general
reasoning to have any effect whatsoever on such hard-core religious
beliefs.

Grow up, and/or get a grip, and/or get over yourself.

Everyone who disagreed with you, disagreed with you with arguments,
logic, facts, and reasoning. You disputed those facts, disagreed with
the conclusions, but for you to then just dismiss people who don't agree
with you as merely "religious", is childish.

Exactly why I think you're wrong -- you're free to go re-read, I stand
by my statements in this thread, and the others. The same arguments
apply. Its not a religion, dear; my conclusions are not a matter of faith.

That's all I have to say on this subject; the conversation has been had,
at length (repeatedly).

I swear, I'm just going to filter you and Rick out to /dev/null today
and leave it at that at this rate. I'm getting worn out of these kinds
of responses.

--

Stephen Hansen
... Also: Ixokai
... Mail: me+list/python (AT) ixokai (DOT) io
... Blog: http://meh.ixokai.io/


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)

iQEcBAEBAgAGBQJMOne0AAoJEKcbwptVWx/lOLIH/AvQnFzvd6wwhJtukZvY45A1
3Xi2TyZ082OXLq80nMVwKWmtvBYDvRCht/Wn7bN0D6/BMGIITqiJSj2bidZ5j1F/
wtH9t0BLL04yIzkjff0dpQk9RXIl0f9DCWz34zDcJvRJte/mbPwXOqY7Pf/NLyOr
4kp48vHbBJHHZo/DTQEBb5mdoN2AZde6l4md3b58nKKuO8+fkLl5M6N2YpvdB4GI
E/BgiUe3sX6Jv628oB24Y0MYg2QxWXXWowJ9QP5fHvP54kgyP9GlOJG1s+eUmm2z
rwrTbxqSidXZvZLEwRbY1IsTnswdWt1Vxt0z3WOnXYc3VIWmh1lZOK2CFHfz0ZI=
=hwxX
-----END PGP SIGNATURE-----
 
M

MRAB

Alf said:
* MRAB, on 12.07.2010 00:37:

That is a misconception.

In Python a variable is declared by having an assignment to it, which
for a local variable may be anywhere within a routine.

If such a variable is used before it's been assigned to, then you get an
uninitialized variable exception. Clearly the variable must exist in
order for the exception to refer to it (not to mention the exception
occurring at all).

def foo():
print( blah )
blah = "this is both an assignment and a declaration causing it to
exist"

foo()

Clearly when the exception is raised, referring to the variable, the
variable exists.

Contrary to your statement that is before the assignment.

However, as stated up-thread, I do not expect facts, logic or general
reasoning to have any effect whatsoever on such hard-core religious
beliefs. And I do not care whether I convince you or not. But I *do not*
want the religious subset of the community to succeed too much in
propagating nonsense idiot beliefs to newbies -- hence the concrete
example that any newbie can try.
How about this:
print("Before:", locals())
x = 0
print("After:", locals())

Before: {}
After: {'x': 0}
 
A

Alf P. Steinbach /Usenet

* Stephen Hansen, on 12.07.2010 04:02:
Grow up, and/or get a grip, and/or get over yourself.

Everyone who disagreed with you, disagreed with you with arguments,
logic, facts, and reasoning. You disputed those facts, disagreed with
the conclusions, but for you to then just dismiss people who don't agree
with you as merely "religious", is childish.

Exactly why I think you're wrong -- you're free to go re-read, I stand
by my statements in this thread, and the others. The same arguments
apply. Its not a religion, dear; my conclusions are not a matter of faith.

That's all I have to say on this subject; the conversation has been had,
at length (repeatedly).

I swear, I'm just going to filter you and Rick out to /dev/null today
and leave it at that at this rate. I'm getting worn out of these kinds
of responses.

Well, the above is flaming, which I predicted.

The alleged facts etc. you're referring are just that, alleged, by you.

In contrast, in debates among non-religious folks facts are /presented/, like
I've done in this thread, e.g. concrete code, instead of like you alleging that
facts have been presented, hinting about things, and so on -- it's pathetic.


Cheers & hth.,

- Alf
 
S

Steven D'Aprano

* MRAB, on 12.07.2010 00:37: [...]
In Java a variable is declared and exists even before the first
assignment to it. In Python a 'variable' isn't declared and won't exist
until the first 'assignment' to it.

That is a misconception.

In Python a variable is declared by having an assignment to it, which
for a local variable may be anywhere within a routine.

Oh, I'm going to regret being sucked into this...

In *CPython*, but not necessarily other implementations, variables which
are local to a function are not kept in a dictionary-based namespace, but
in slots in the code object (not to be confused with __slots__ used for
classes). Python has STORE_FAST and LOAD_FAST byte-codes for accessing
locals.

This is intended as a speed, and possibly memory, optimization. I don't
believe this is a requirement though, so implementations may not do this.

It is true that the slot is created at compile time, and in *that sense*,
local variables exist before they are bound. I'm not entirely convinced
that this is the only sense that matters, but never mind. The error
message given exposes this to the user:
.... print x
.... x = 1
....Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment


If you try this with a global, you get this:
.... global x
.... print x
....Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in f
NameError: global name 'x' is not defined

In this case, there's no doubt that global variable "x" doesn't exist at
all -- there is no key "x" in the global namespace.


It seems to me that "a slot to hold the variable is created for local
variables" is an implementation detail, not a language feature. CPython
could easily hide the difference by changing the exception from
UnboundLocalError to:

NameError: local name 'x' does not exist

and nobody would be any wiser. (Well, perhaps people who catch
UnboundLocalError, but why would you do that?)

I also note that UnboundLocalError is a subclass of NameError, so
"variable exists but is not bound" is considered to be a special case of
"variable doesn't exist" rather than a completely independent case. In
that sense, I think I'm on solid ground to say that in Python variables
don't exist until they are bound to a value, and leave it to pedants like
you and I to mention that for CPython local variables have space reserved
for them by the compiler before they are bound.
 
A

Alf P. Steinbach /Usenet

* MRAB, on 12.07.2010 04:09:
How about this:

print("Before:", locals())
x = 0
print("After:", locals())


Before: {}
After: {'x': 0}

How about it?

Note that you get the same result if you do

x = "blah"
def foo():
# print( x ) # Causes uninitialized variable exception here
print( "Before:", locals() )
x = 0
print( "After:", locals() )

However, if you remove the local assignment to x, then the out-commented print
statement will no longer cause an exception, it will then refer to the global.

The reason that it does throw an exception when you do have the local
assignment, is that the local x exists at that point. If it didn't exist it
could not have any effect. Things that don't exist generally have no effect,
except in the minds of the religious, like angels and so on.

On the basis of what locals() reports it should be OK to refer to the global x
as above. Judging by locals(), there's no local x that could get in the way. But
since it is not OK to refer to the global x, the result of locals() has nothing
to do with that: it doesn't tell you about the local x -- and no, the Python
interpreter does not look forward in time to see that it will appear.

In passing, I should perhaps have told you up front, your argument has nothing
substantial to do with the article you originally responded to, about the
semantics of variables. Your argument is the assertion that different languages
can't have similar or identical semantics for some feature. That's nonsense in
itself, plus, as you've seen, the difference that you focused on is not there,
and, third, what you do maintain is not there, doesn't exist, has a real effect.


Cheers & hth.,

- Alf
 
G

geremy condra

* MRAB, on 12.07.2010 00:37: [...]
In Java a variable is declared and exists even before the first
assignment to it. In Python a 'variable' isn't declared and won't exist
until the first 'assignment' to it.

That is a misconception.

In Python a variable is declared by having an assignment to it, which
for a local variable may be anywhere within a routine.

Oh, I'm going to regret being sucked into this...

In *CPython*, but not necessarily other implementations, variables which
are local to a function are not kept in a dictionary-based namespace, but
in slots in the code object (not to be confused with __slots__ used for
classes). Python has STORE_FAST and LOAD_FAST byte-codes for accessing
locals.

This is intended as a speed, and possibly memory, optimization. I don't
believe this is a requirement though, so implementations may not do this.

It is true that the slot is created at compile time, and in *that sense*,
local variables exist before they are bound. I'm not entirely convinced
that this is the only sense that matters, but never mind. The error
message given exposes this to the user:
...     print x
...     x = 1
...Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment


If you try this with a global, you get this:
...     global x
...     print x
...Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 3, in f
NameError: global name 'x' is not defined

In this case, there's no doubt that global variable "x" doesn't exist at
all -- there is no key "x" in the global namespace.


It seems to me that "a slot to hold the variable is created for local
variables" is an implementation detail, not a language feature. CPython
could easily hide the difference by changing the exception from
UnboundLocalError to:

NameError: local name 'x' does not exist

and nobody would be any wiser. (Well, perhaps people who catch
UnboundLocalError, but why would you do that?)

I also note that UnboundLocalError is a subclass of NameError, so
"variable exists but is not bound" is considered to be a special case of
"variable doesn't exist" rather than a completely independent case. In
that sense, I think I'm on solid ground to say that in Python variables
don't exist until they are bound to a value, and leave it to pedants like
you and I to mention that for CPython local variables have space reserved
for them by the compiler before they are bound.

Very interesting, and a pleasant change of tone to boot. Thanks.

Geremy Condra
 
S

sturlamolden

Oh, I wouldn't give that advice. It's meaningless mumbo-jumbo. Python works like
Java in this respect, that's all; neither Java nor Python support 'swap'.

x,y = y,x
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top