You'll never win that argument with the gcc developers. If you
rely on undefined behavior in the c language standard, they have
in the past, and will continue to, feel free to ignore those cases.
If you plan on ignoring this issue, just be prepared to see a
testcase failure in the python testsuite when python is built with
The logging module currently contains some weird-looking code that is
there to maintain 1.5.2 compatibility (*). I don't think that's needed
any more; neither does Vinay. I propose as a project for someone to
clean it up; perhaps compatibility could be maintained with 2.2 but
that's probably as far back as it needs to go. Linux distros all come
with 2.2 or newer these days.
The logging module is currently listed in PEP 291 as requiring
compatibility with 1.5.2; my proposal is to remove this or replace it
with 2.2 (Vinay even proposed 2.4).
(*) I found an example of code testing "if string.find(s, t) != 0",
thinking it was a bug attempting to write "if t in s", but which Vinay
identified as a 1.5.2 idiom for "if not s.startswith(t)"...
--Guido van Rossum (home page: http://www.python.org/~guido/)
There's a unit test "test_mutants" which I don't understand. If anyone
remembers what it's doing, please contact me -- after ripping out
dictionary ordering in Py3k, it stops working. In particular, the code
in test_one() requires changes, but I don't know how... Please help!
--Guido van Rossum (home page: http://www.python.org/~guido/)
I don't want to make any more changes to 2.5 unless we absolutely have
to. I also don't want to lose fixes. How about for anything that
should be resolved in 2.5, but wait for 2.5.1 we set the tracker item
to: Group 2.5, Resolution: Later, Priority 7.
Then it should be easy to find these things.
I noticed in Python/ceval.c that LOAD_GLOBAL uses a dictionary lookup,
and was wondering if that can be optimized to a simple array lookup.
If i'm right there are 3 kinds of name lookups: locals, outer
scopes(closures), and globals. (not counting attribute lookup). Locals
are identified by, either the presence of assignments, or their presence
in the arg list. So all name lookups can be classified into the 3 types
at compile/load time.
Since we know, at load time, which names are global.. Can't we simply
build a global name table and replace LOAD_GLOBALs with a lookup at the
corresponding index into the global name table?
The module's dict object will need to be special so that whenever a name
gets 'set', the global name table should get updated.
Is this optimization possible or have i missed something?
I've been working on enhancing xrange and there are a bunch of issues
to consider. I've got pretty much complete implementations in both C
and Python. Currently xrange is 2 objects: range and the iter.
These only work on C longs. Here's what I propose:
* Add deprecation warning if a float is passed to xrange (currently
* Allow int, long, float, or obj.__index__
* Implement xrange in python
* Implement iterator over C longs (or Py_ssize_t) in C
* Implement iterator over Python longs in Python (* may lose __length_hint__)
* Capture the values on construction, so mutating objects wouldn't
The idea is to expand xrange's capabilities so that it can replace range in 3k.
I've profiled various combinations. Here are the various results
normalized doing xrange(0, 1e6, 1):
Run on all integer (32-bit) values for start, step, end:
C xrange and iter: 1
Py xrange w/C iter: 1
Py xrange w/Py iter (gen): 5-8
Py xrange w/Py iter (class): ~30
So having xrange in python is the same speed as if xrange is written
in C. The important part is that the iterator needs to be written in
C for speed. If we use a generator, something like:
while value < end:
value += step
The result is ~5 times slower in a release build and 8 times slower in
a debug build than with an iterator implemented in C. Using a
generator means that there is no __length_hint__. If we go with a
full class that has a __length_hint__ the result was ~32 times slower
in a debug build.
The Python impl is about 1/10th the size of the C impl, though is
lacking some comments.
Run on Python longs the result is somewhat interesting. The Python
based iterator is faster. There's probably a bug in the C version,
but given that there is a lot of object allocation, I wouldn't expect
the C version to ever be much faster than a similar Python version.
Plus the Python version is trivial (same as above) for ints or longs.
The C version for longs is quite a bit of code.
Run on all Python longs (still 0..1e6, but sys.maxint..(sys.maxint +
1e6) is the same):
C xrange and iter: 1.4
Py xrange w/C iter: not tested
Py xrange w/Py iter (gen): 1
Py xrange w/Py iter (class): 4
* The generator version above doesn't support floats. We could
easily support floats with a different calculation that would be
slightly more expensive, but not have accumulated error.
* By using the generator version, __length_hint__ gets dropped. This
means that converting the iterator into a sequence could be slightly
more costly as we have to increase the allocation. This would only
happen if any of start, step, end weren't an int.
* With a python implementation there is a little bit of bootstraping
that is necessary to get the iter implemented in C into the xrange
object implemented in Python
* Since xrange is implemented in Python, it can be changed.
* The Python code is much easier to understand than the C code (there
is at least one bug in the current C version where -sys.maxint -1
isn't always displayed properly).
Hopefully this is all understandable. If I left anything out, Thomas
will remind me.
I have been spending my Google sprint time on writing and implementing PEP
362 (http://www.python.org/dev/peps/pep-0362/), which finally defines
Signature objects for functions. With the implementation at a place I am
happy with, I wanted to ask about the open issues with the PEP.
The first question is whether to have Signature objects on all functions by
default or to leave it in the 'inspect' module and have it be something
totally optional. My vote is the latter for now and we can add them to all
functions if they turn out to be useful and popular.
The second open issue is how to handle binding arguments to tuple parameters
for the Signature.bind() method. If you have the function ``def foo((a, b):
pass``, how do you have the Signature.bind() method handle 'a', and 'b'?
You can either take the proposed arguments and in the dict mapping arguments
to parameters have an entry for 'a' and 'b' individually, or have an entry
for '(a, (b,))'. My vote is the latter since you cannot address 'a' or 'b'
individually as keyword arguments and this makes more sense with function
annotations since they won't apply to 'a' and 'b' individually but instead
to the entire tuple. Either way there is the issue of exhausting an
iterator (like a generator) trying to find out if it is the proper length to
unpack, for which I raise a TypeError instead of exhaust a possibly mutable
At 01:44 AM 8/24/2006 +0200, Igor Bukanov wrote:
>Regarding yield in the finally problem:
>The current implementation throws RuntimeException after the yield
>transfer the control back to the close method. If that is changed to
>reporting a bad behavior and rethrowing GeneratorExit or its hidden
>analog as suggested at the point of yield inside the generator, that
>would nicely unwind possible outer finally blocks and close the
>generator in any case.
This approach has already been proposed and rejected multiple times. A
badly-behaving generator is broken and asking it to handle the error of its
own brokenness will lead only to grief. Once the generator yields
inappropriately, it has proven it cannot be trusted. It is only
compounding the generator's insanity to ask it to handle this error!
At 04:10 PM 8/23/2006 -0700, Guido van Rossum wrote:
>IIUC this is how return currently works -- in some sense it's an
>exception, but it can't be caught, and it won't escape from the
>current frame. Ditto for break/continue.
>The generator extensions are still very young, and I'm not against
>changing them somewhat in 2.6 or py3k. Perhaps GeneratorExit can be
>replaced by a treatment similar to the treatment of return. But I'm
>not sure it helps with the original problem;
It depends on what you're referring to as "the original problem". If you
mean the problem Bob Ippolito opened a bug for, then yes, it does not solve
that problem. But I think we agree that *that* problem doesn't actually
However, it *does* solve the problem(s) that Igor Bukanov brought up,
namely that GeneratorExit is unintuitive and unnecessary. :) It also
fixes the problem of calling close() or GC'ing a generator written for an
earlier version of Python, that yields inside a try-except.
>In a generator, a yield
>in the finally clause still needs to be dealt with somehow.
And we should keep the existing PEP-defined behavior for dealing with
it. That is, my understanding is that the only part of close()'s
definition that would change is the 'throw(GeneratorExit)' bit.
I just wish this had been proposed some time much sooner, like maybe not
long after I did the original implementation of
throw()/close()/etc. During the original discussion, I'd have been more
skeptical of a return-based approach. But knowing what I know now about
the implementation, making it based on return instead would be trivial. A
proof-of-concept patch I just whipped up adds 7 lines to the hook code in
ceval.c (to determine whether WHY_RETURN or WHY_EXCEPTION should be used),
and 5 lines to gen_close() in genobject.c.