Recent Posts
- From Research to Personas
- Read My Mind
- I Feel Your Pain
- Interactions 08 | Thoughts
- IxDA Interaction 08 | Savannah
- Service/Product/Service
What’s In The Loop
- Reading Online
- UX Pioneers
- Am I Seeing Python Everywhere?
- Lazy mom pushes stroller while on a Segway
- The antithesis of usability...
- Secretary with lightning quick hands
- Cooper | Insights | Journal of Design | Articles | About Face 3: Foreword
- Orange Cone: An unusual addition to the UI collection
- National Design Awards | Cooper-Hewitt, National Design Museum
- Logic+Emotion: Breaking Up With Advertising
- Read More…
Archives
Categories
RSS – The Loop
The Loop
About Python 2.5
Python 2.5 came out just a couple days ago. It introduces a whole joyous pile of new features I'm eager to put to work for me.
I’m borrowing the format of Andrew Kuchling’s What’s New in Python 2.5, except I have re-ordered these topics in the order I find them interesting.
Conditional Expressions
For ages now, PHP developers have known and loved a borrowing from C, the ternary operator:
condition ? true_value : false_value
Ruby developers haven’t needed such a feature, because everything in Ruby is an expression, so they could do this:
if condition then true_value else false_value end
Now, in Python 2.5, we get a variation on this time honored tradition:
true_value if condition else false_value
Expect to start seeing this kind of behavior from your web developers:
'<span' + ' class="selected"' if selected else '' + '>'
The with Statement and Context Managers
Since Python 2.2, we’ve been able to have functions return values to a for loop. This is the generator facility, and it depends on the yield keyword.
One of Ruby’s core features is that anything can yield as much as it wants to. For example, if you want to open a file, you’re recommended to use this syntax:
open('filename.txt', 'r') do |file|
puts file.read # use the file
end
This way, Ruby takes care of the opening and the closing of the file. It’s probably implemented somewhat like this:
def open(filename, mode='r')
file = ... # perform low-level file opening routine
if block_given?
yield file
file.close
else
file
end
end
In Python, you could accomplish the same thing with generators:
def my_open(filename, mode='r'):
file = open(filename, mode)
yield file
file.close()
Using such a function would look a little strange though:
for file in my_open('filename.txt'):
print file.read() # use the file
The new with: statement gives Python a more elegant solution to the using side of things:
with open('filename.txt') as file:
print file.read() # use the file
The implementation side of things is more interesting, as usual. Like generators, there’s a simple method and a complex method for implementing a context manager. The simple way looks like this (example borrowed from the PEP):
from contextlib import contextmanager
@contextmanager
def db_transaction(connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
This would be used like so:
db = DatabaseConnection()
with db_transaction(db) as cursor:
cursor.execute('INSERT INTO ...')
cursor.execute('DELETE FROM ...')
This could also be implemented like this, if you want to do it the long way:
class DatabaseConnection:
...
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
def __exit__ (self, type, value, traceback):
if traceback is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
Using this variation is a bit different:
db = DatabaseConnection()
with db as cursor: # notice this is not a function call
cursor.execute('INSERT INTO ...')
cursor.execute('DELETE FROM ...')
Unified try/except/finally
In older versions of Python, there was a try/except block and a try/finally block. Now they’ve been merged, so you can throw some code into a try block, catch some exceptions if they should occur, and then perform clean up regardless of whether there was an exception or not.
One interesting aspect of the new try/except statement is that there is an else: block. The idea behind it: you can put code in there which should execute after the code in the try: block succeeds, but exceptions raised in executing it are not to be handled by the except statements in the current try block. For example:
try:
some_unsafe_operation()
except ParticularFault:
handle_particular_fault()
except:
handle_generic_problems()
else:
do_some_other_operation()
finally:
clean_up()
If something goes wrong in some_unsafe_operation(), it will definitely be handled here, either by the handle_particular_fault() function or by the handle_generic_problems() function which handles all the other types of exceptions. But if anything should go wrong in do_some_other_operation(), that exception will bubble up the stack normally (of course, clean_up() will still be called). If you put the code in the else: block into the try: block, any exceptions it raised there would be handled by one of the except: blocks. A subtle difference I’m not convinced will ever really be useful, but it’s good to know that it’s there.
Partial Function Application
Pretend for a moment you want a function that takes a number and returns a function that adds that number to its own argument. If you implemented this the way Guido wants, you would have this:
def adder(amount):
def internal(x):
return x + amount
return internal
If you implemented this like a functional programmer, you might arrive at this:
def adder(amount):
return lambda x: x + amount
Now, you can implement it the way a real ML-school functional programmer would:
from operator import __add__
from functools import partial
def adder(amount):
return partial(__add__, amount)
What’s the improvement? Well, in my book, it’s an improvement that you no longer have to actually create a new function, you can just call another function with an argument of a function and get a new function back. I think this may turn out to be useful in writing Python-style @decorators, but it’s not likely to come up a lot for most people.
New Libraries
I’m pleasantly surprised to see that the infamous SQLite library is now an official part of Python. Along with it, a part of ElementTree has joined the ranks, which I had never heard much about but many libraries I’ve downloaded lately seem to depend on. I’m also pleased to see a WSGI reference implementation, since I’ve been learning Pylons lately and appreciate the idea behind it.
There are plenty of other smaller changes.
Speed Enhancements
Exception handling is 30% faster, thanks to a change to use new-style classes for all exceptions. The peephole optimizer now performs constant folding, meaning statements like ‘Hello ’ + ‘World’ are compiled into ‘Hello World’ in the bytecode, rather than a string operation on two strings. A variety of small improvements were made across the board, including changes to Unicode strings, regular expressions, ordinary function calls, and importing.
New Generator Features
Generators now have three new methods: send(), throw(), and close(). The documentation says this:
The cumulative effect of these changes is to turn generators from one-way producers of information into both producers and consumers.
Generators also become coroutines, a more generalized form of subroutines. Subroutines are entered at one point and exited at another point (the top of the function, and a return statement), but coroutines can be entered, exited, and resumed at many different points (the yield statements).
An excellent thing about coroutines is that they are a great threading replacement, with much less overhead and generally much easier to follow paths of execution. It’ll be interesting to see what happens on this note. As the PEP author notes, “We’ll have to figure out patterns for using coroutines effectively in Python.” So this should be really cool once we learn more about it.
Absolute and Relative Imports
Apparently, a future version of Python is going to do away with the feature that from foo import * starts the module lookup in the current directory. To accomplish the same thing, you’ll have to use from .foo import * instead. I’m not sure I like this change, since Python’s modules are one of its most powerful features.
Adding confusion, you’ll be able to tell Python to start the lookup above the current folder by prepending additional periods: from ...foo import * begins the lookup at the parent of the parent of the current directory.
Further complicating things, the documentation says the leading dot functionality will not be usable from import foo, only the from foo import ... syntax.
This one gets the chin-scratch from me. Hopefully between 2.5 and 2.7, when the absolute import functionality is set to become standard, we’ll see some more exposition about why this is good and necessary.
Trackbacks
Trackback specific URI for this entryComments
Leave a comment?


