By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,310 Members | 1,466 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,310 IT Pros & Developers. It's quick & easy.

Python 2.4: Why only assignments to None are forbiden?

P: n/a
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden. It's a common mistake to do things
like this:
def getFileName(file):

.... parts=file.split('/')
.... return parts('/')[-1]

Specially if you come from python 2.1.x where "file" didn't exist.
Instead, there was "open"

On the example's context, file is a string and won't cause any damage
because it is inside a function, so, the scope is local and it will be
deleted after the function call. But think what would happen if somebody
defines "file" as a global variable and other people use that code? For
the author won't be any consequences at all, because if s/he does this,
it means that probably s/he isn't working with files, but if somebody
else takes that code and doesn't see this, then s/he will invest some
time trying to find the bug.

Doing this validation for python 2.4.x will break some things, like the
validation with "None" does. But I think it's better when you now that
you are trying to use a "reserved word", you could as well use the "str"
as an example, which I think is also common on newies.

Regards,
Josef
Jul 18 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a

Forbidding assignment to arbitrary things seems like a bad idea.

I remember some learning manual recommended this (or the equivalent):

def do_stuff_to_bob(bob=None):
if not bob:
bob = ["carol","ted","alice"]
#do stuff to bob
return bob

otherwise bob would already be defined from the last call (because it is a
mutable type? I can't remember.). How else to handle this in 2.4?

On Friday 12 November 2004 01:11 pm, Josef Meile wrote:
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden.

James
Jul 18 '05 #2

P: n/a
Josef Meile <jm****@hotmail.com> writes:
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden. It's a common mistake to do things
like this:
>>> def getFileName(file):
... parts=file.split('/')
... return parts('/')[-1]

Specially if you come from python 2.1.x where "file" didn't exist.
Instead, there was "open"

On the example's context, file is a string and won't cause any damage
because it is inside a function, so, the scope is local and it will be
deleted after the function call. But think what would happen if
somebody defines "file" as a global variable and other people use that
code?
That may not be great style, but it's not a mistake: file is used as a
local variable, so the global binding doesn't enter into it. And with
this short of function, I wouldn't worry too much.

Longer functions, yes, you might get bit, especially with other
builtins, like str and dict.
Doing this validation for python 2.4.x will break some things, like
the validation with "None" does. But I think it's better when you now
that you are trying to use a "reserved word", you could as well use
the "str" as an example, which I think is also common on newies.


I believe the idea behind making None non-assignable is one of
optimization: it's used a lot, and each time, the runtime has to do a
lookup to find the current value.

But making other builtins unassignable, while nice, removes some of
the dynamism that makes Python nice.

Recently, I needed to check what files my program was opening (and not
closing; I was running out of file descriptors). The easy way to do
that was to override the builtin open() function, returning a proxy
object that would annouce it's been opened, and when it's been closed.
This isn't quite the same thing: I had to assign to __builtin__.open
so that all modules would get my new open. However, if open were
declared unassignable, I'll bet you that it would be bound at
*compile* time instead of runtime, and this trick wouldn't work anyways.

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Jul 18 '05 #3

P: n/a
Josef Meile wrote:
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden. It's a common mistake to do things
like this:
>>> def getFileName(file):
... parts=file.split('/')
... return parts('/')[-1]

Specially if you come from python 2.1.x where "file" didn't exist.
Instead, there was "open"


Well, it's not really a mistake, because it works just fine and causes
no problems. I use builtin names often, as they are annoyingly very
convenient local variables. I try not to, but it still happens
(especially file, though I make sure to distinguish between files and
filenames).

Anyway, it's a big backward compatibility issue. No one ever reassigns
None, so it's not a problem. Maybe True and False will go this way too
(though that *will* cause backward compatible problems with code that
preceded the True/False builtins, and so created its own True/False
objects).
On the example's context, file is a string and won't cause any damage
because it is inside a function, so, the scope is local and it will be
deleted after the function call. But think what would happen if somebody
defines "file" as a global variable and other people use that code? For
the author won't be any consequences at all, because if s/he does this,
it means that probably s/he isn't working with files, but if somebody
else takes that code and doesn't see this, then s/he will invest some
time trying to find the bug.


There are proposed optimizations that depend on there being no
global-level redefinition of builtins, and there's a couple PEPs about
this. I think the ideas have been viewed favorably, but the
implementations haven't been fully fleshed out, and kind of fell by the
wayside. They could still be picked up. There were a few people who
were concerned; I think boost particularly defines some public symbols
like boost.int, which this would disallow.

Anyway, the much more conservative proposal that disallows global
variables that share a name with a builtins seems reasonable and largely
backward compatible.

--
Ian Bicking / ia**@colorstudy.com / http://blog.ianbicking.org
Jul 18 '05 #4

P: n/a
On Fri, 12 Nov 2004 13:08:30 -0800, James Stroud <js*****@mbi.ucla.edu> wrote:

Forbidding assignment to arbitrary things seems like a bad idea.

I remember some learning manual recommended this (or the equivalent):
Two things wrong in the following, as noted:def do_stuff_to_bob(bob=None): #XXX# > if not bob:
if bob is None: # this is the usual gerneral idiom, so that e.g., one could
# distinguish from a caller passing a legitimate empty list []
# (though of course you could use if not bob if that's what you meant ;-) bob = ["carol","ted","alice"] # ^^^^^ -- this does not assign to None, it rebinds bob,
# which has no effect on the previously bound object (in this case None)
# That's a serious misunderstanding of python's assignment semantics, which
# your momentary lapse should not be allowed to promote to newbies ;-)
#do stuff to bob
return bob

otherwise bob would already be defined from the last call (because it is a
mutable type? I can't remember.). How else to handle this in 2.4?

On Friday 12 November 2004 01:11 pm, Josef Meile wrote:
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden.

James


Python 2.4b1 (#56, Nov 3 2004, 01:47:27)
[GCC 3.2.3 (mingw special 20030504-1)] on win32
Type "help", "copyright", "credits" or "license" for more information.
None = 'foo' SyntaxError: assignment to None 1234 = 'foo' SyntaxError: can't assign to literal bob = None
bob
repr(bob) 'None' bob = 1234
bob

1234

Regards,
Bengt Richter
Jul 18 '05 #5

P: n/a
Josef Meile wrote:
I think in general assignments to built-in types, functions, and
variables should be also forbiden.


Very little in Python should be *forbidden*. Certainly not
something like this! Maybe make it hard to do inadvertently.
Maybe require it be an explicit call to a special function
or something. But forbid it? Please no!

One perfectly good reason to assign to builtins (and there are others,
I'm sure) is to provide a "mock" function to replace a standard
one, for use during automated testing. See, for example, the
reference to a "mock filesystem" that I posted a few days ago,
where you can insert your own "open" function in the builtin
namespace, providing a fake filesystem that intercepts all
file creation and reading and simulates the behaviour.

You can do this easily on a single module, or several, just
by inserting a global into the module(s) in question, but if
you want to do it through an application it becomes a real
burden (and a way to let bugs leak through) to have to do it
that way. A single assignment override to the standard open
is much more effective and safe.

Every time this issue comes up I feel compelled to point out
this perfectly useful and valid use of assigning to builtins...
I really hope the message gets through.

-Peter
Jul 18 '05 #6

P: n/a
Ian Bicking <ia**@colorstudy.com> wrote in message news:<ma**************************************@pyt hon.org>...
Josef Meile wrote:
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and
variables should be also forbiden. It's a common mistake to do things
like this:
>>> def getFileName(file):

... parts=file.split('/')
... return parts('/')[-1]

Specially if you come from python 2.1.x where "file" didn't exist.
Instead, there was "open"


Well, it's not really a mistake, because it works just fine and causes
no problems. I use builtin names often, as they are annoyingly very
convenient local variables. I try not to, but it still happens
(especially file, though I make sure to distinguish between files and
filenames).


I have the same problem.

Perhaps it would have better if "file" were named "File" instead.
Jul 18 '05 #7

P: n/a

"Josef Meile" <jm****@hotmail.com> wrote in message
news:41******@pfaff2.ethz.ch...
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and variables
should be also forbiden.


As Ian points out in another response, there's been some
discussion about making a fairly large subset of the builtins
name space immutable, and also to disallow shadowing
of builtins with identical names in module scope.

The main reason for this is performance optimization.
Right now, the len() function, for example, requires
a lookup and two (!) function evaluations. If the
compiler could trust that len() was always the function
in the builtins, then it could compile a direct call to the
__len__() function on the object, at a savings of the
lookup and one function call. There is a considerable savings
projected over the entire name builtin name space.

There's always a tension between protecting people
against common errors and keeping the language
as flexible and dynamic as possible. I'd prefer that
the editors and IDEs take up the slack. For example,
I found that JEdit colorized builtins differently from
ordinary names. This pointed out a few bad habits
I'd fallen into, without taking away the option of
overriding something when I really wanted it.

In any case, it won't happen in 2.4.x. That kind
of change will wait for a full point release: 2.5
or later.

John Roth


Jul 18 '05 #8

P: n/a
Ian Bicking <ia**@colorstudy.com> wrote:
Anyway, the much more conservative proposal that disallows global
variables that share a name with a builtins seems reasonable and largely
backward compatible.


This still sounds undesirable to me.

- it requires new authors to know and avoid all the builtins, even
those they have no intention of using;

- afterwards, adding any new builtins becomes a potentially
app-breaking proposition.

Protecting None, False and True seems fine to me; they're extremely
common and part of the syntax itself in most languages. But banning a
global variable called 'license', for example, or a class 'Warning',
would be going too far IMO.

--
Andrew Clover
mailto:an*@doxdesk.com
http://www.doxdesk.com/
Jul 18 '05 #9

P: n/a
On Sat, 13 Nov 2004 08:04:28 -0600, "John Roth" <ne********@jhrothjr.com> wrote:

"Josef Meile" <jm****@hotmail.com> wrote in message
news:41******@pfaff2.ethz.ch...
Hi,

Textually from the highlights of python 2.4:

"Assigning to None - the compiler now treats assigning to None as a
SyntaxError."

I think in general assignments to built-in types, functions, and variables
should be also forbiden.


As Ian points out in another response, there's been some
discussion about making a fairly large subset of the builtins
name space immutable, and also to disallow shadowing
of builtins with identical names in module scope.

The main reason for this is performance optimization.
Right now, the len() function, for example, requires
a lookup and two (!) function evaluations. If the
compiler could trust that len() was always the function
in the builtins, then it could compile a direct call to the
__len__() function on the object, at a savings of the
lookup and one function call. There is a considerable savings
projected over the entire name builtin name space.

There's always a tension between protecting people
against common errors and keeping the language
as flexible and dynamic as possible. I'd prefer that
the editors and IDEs take up the slack. For example,
I found that JEdit colorized builtins differently from
ordinary names. This pointed out a few bad habits
I'd fallen into, without taking away the option of
overriding something when I really wanted it.

In any case, it won't happen in 2.4.x. That kind
of change will wait for a full point release: 2.5
or later.

John Roth

I don't mind things being locked or unlocked by sensible
default if I have a key. I.e., I'd like some way of telling
the compiler to generate current-style lookup code for a particular
builtin that might be optimized in the future.

Since this is a compile-time issue , perhaps it is time to consider
a pragma statement as a framework for telling python pre-runtime things
like optimization info? E.g., pragma could send in-context meta-info
to various python infrastructure components using python method call syntax
which the compiler could recognize in the token stream and compile and
execute in its working environment right then. So e.g.,

pragma compiler.override(len=True, cmp=False)

would say "after this statement in the token stream, generate code for
old-style lookup of len (allowing overriding) and cease to do that for cmp."

Right now we can do this:
def calledat(level=2): # default = caller's caller ... f = sys._getframe()
... for _ in xrange(level): f = f and f.f_back
... return f and '%s line %s'%(f.f_code.co_name, f.f_lineno) or '???'
... def showlencall(seq): ... print '---> len(%r) from %s'%(seq, calledat(2))
... __builtins__.len <built-in function len> def showlencall(seq): ... print '---> len(%r) from %s'%(seq, calledat(2))
... return __builtins__.len(seq)
...

Here (or at the top of this scope) we would in the future need:

pragma compiler.override(len=True) # be able to specify scope other than local??
len = showlencall
def foo(x): ... return len(x)
... foo(range(4))

---> len([0, 1, 2, 3]) from foo line 2
4

Not that this shows implicit calls to __len__ in various places...
Hm, that might make an interesting pragma

pragma compiler.methodhook(__len__= my_len_tracer)

I better stop here ;-)

Regards,
Bengt Richter
Jul 18 '05 #10

P: n/a
Peter Hansen wrote:
One perfectly good reason to assign to builtins (and there are others,
I'm sure) is to provide a "mock" function to replace a standard
one, for use during automated testing.


That's understandable, but it doesn't work for None. At the C
level there is a Py_None object which is the same singleton object
used by None. If you replace the builtin None with a mock None
then almost certainly there will be strange effects.

Eg,

def spam():
print "Here there be Vikings"

x = spam()

At this point, x contains the real None and not the mock one.

class MyList(list):
def get(self, item):
if item.startswith("__"):
raise AccessDenied(item)
return list.get(item)

x = MyList().get("wensleydale")
Again, x is the real None object and not the mock one.

So if reasonable code did the following

if x is None:
print "Sorry, not even wensleydale"
else:
print "Yes, we have it"

then it would break under the mock None case.

In theory it could be possible to make this work. Setting
None in builtins could change some sort of proxy object at
the C level, and ... though the object ids wouldn't be right.
Hmmm. It would be a lot of work for very, very little gain.

So while we do have

Special cases aren't special enough to break the rules.

it's more than trumped by

Although practicality beats purity.

It's almost impossible to make a proxy None object work
correctly.

In a related topic, would you like to have a proxy for the
numbers 0, 1, 2, etc.? Is None special because it's a
variable name that cannot be reassigned or is it not special
because it's just like other builtin objects that cannot
be replaced by user-defined objects?

Andrew
da***@dalkescientific.com
Jul 18 '05 #11

P: n/a

"Andrew Dalke" <ad****@mindspring.com> wrote in message
news:ei*******************@newsread1.news.pas.eart hlink.net...
Peter Hansen wrote:
One perfectly good reason to assign to builtins (and there are others,
I'm sure) is to provide a "mock" function to replace a standard
one, for use during automated testing.


That's understandable, but it doesn't work for None.


Peter was not suggesting that replacement of None be allowed but that
replacement of things like file() should continued to be allowed and not
prohibited as someone (I believe other than the OP) suggested.

Terry J. Reedy

Jul 18 '05 #12

P: n/a
Terry Reedy wrote:
Peter was not suggesting that replacement of None be allowed but that
replacement of things like file() should continued to be allowed and not
prohibited as someone (I believe other than the OP) suggested.


Ahh, thank you. I didn't catch the shift in topic.

Andrew
da***@dalkescientific.com
Jul 18 '05 #13

P: n/a
Bengt Richter wrote:
Since this is a compile-time issue , perhaps it is time to consider
a pragma statement as a framework for telling python pre-runtime things
like optimization info? E.g., pragma could send in-context meta-info
to various python infrastructure components using python method call syntax
which the compiler could recognize in the token stream and compile and
execute in its working environment right then. So e.g.,

pragma compiler.override(len=True, cmp=False)


There's a recipe for doing something very similar to this with the
current Python:

http://aspn.activestate.com/ASPN/Coo.../Recipe/277940

--
Ian Bicking / ia**@colorstudy.com / http://blog.ianbicking.org
Jul 18 '05 #14

P: n/a
On Mon, 15 Nov 2004 00:35:12 -0600, Ian Bicking <ia**@colorstudy.com> wrote:
Bengt Richter wrote:
Since this is a compile-time issue , perhaps it is time to consider
a pragma statement as a framework for telling python pre-runtime things
like optimization info? E.g., pragma could send in-context meta-info
to various python infrastructure components using python method call syntax
which the compiler could recognize in the token stream and compile and
execute in its working environment right then. So e.g.,

pragma compiler.override(len=True, cmp=False)


There's a recipe for doing something very similar to this with the
current Python:

http://aspn.activestate.com/ASPN/Coo.../Recipe/277940

Yes, that's a nice clever decorator thing for certain kinds of optimization
(by Raymond Hettinger), but if file='something' were disallowed, and you
wanted to do it in a function, I don't think a decorator would get
control early enough to do anything about it, even if there were a hook
for unlocking the bindability of file. But yes, in general, I can see why you
were reminded ;-)

Regards,
Bengt Richter
Jul 18 '05 #15

P: n/a
I'm seeing Python mentioned a bit more in "help wanted" job descriptions, reflecting, I suppose, a modicum of inroads Python is making into various development or IT environments.

As I contemplated a posted job for a friend who meets the requirements, save the mention of desired Python competence, it occurred to me that it wouldnot be hard for him (a competent SW engineer) to become competent in Python; in fact, that's a real Python strong point.

If we see Python increasingly in help wanted ads, one might expect competent job seekers to take the week or two it would take to get waist deep in Python (or do I over-estimate: is it more like two days for a competent SW engineer to learn and get practiced in Python?)

Python is so easy to learn, it's a natural choice for someone wanting to gain a broader skillset; when breadth of language knowledge becomes important, Python is an easy target.

If the pick-up of Python as an "extra" language becomes a trend, then I believe the tipping point will be reached, and a positive feedback loop will see the language adopted and employed much more widely, and blossom even further in the hands of a larger army of volunteers.
Of course, this would be the end of the IT world, for Python ruins one for programming in much of anything else.
.... yes, I only smoke the good stuff.

What is a Perl?
Eric Pederson
:::::::::::::::::::::::::::::::::::
domainNot="@something.com"
domainIs=domainNot.replace("s","z")
ePrefix="".join([chr(ord(x)+1) for x in "do"])
mailMeAt=ePrefix+domainIs
:::::::::::::::::::::::::::::::::::

Jul 18 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.