Some "pythonic" suggestions for Python
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Thu Nov 8 18:25:02 EST 2007
On Thu, 08 Nov 2007 15:00:03 -0500, Frank Samuelson wrote:
> 1. Currently in Python
> def foo(x,y): ...
> assigns the name foo to a function object. Is this pythonic?
>
> Why not use the = operator like most other assignments?
Why? What benefit do you gain?
> Define function objects as "function"s, let users put them where they
> want to. Get rid of lambda, get rid of def, only use = for assignments.
So you remove two keywords. That's a plus. But then you have to create a
WHOLE lot more syntax to support it, and that's about a thousand minuses.
Python has very little syntax, and the designers are (rightly) very
resistant to adding more.
> foo = function(x,y) x+y*2 # Example S language code
This would currently be a syntax error, hence the need for new syntax.
Also, function() couldn't be a normal type, or even a built-in function,
because it has to have special syntax:
name = function(*argument_list) expression
It's also not clear how you expect this to work with anything more
complex than a single expression. How do you handle statements and
multiple returns?
def foo(x, y):
L = []
try:
if x[y] % 2:
print x, y
return y
return x[y]
except:
return None
> bar = foo
But you can still do this with Python:
def foo(x, y):
return x+y*2
bar = foo
> 2. Allow sequences to be indices:
> >>> s=["hello", 6, 33, "none"]
> >>> x= [1,3]
> >>> [ s[y] for y in x] # Current verbose version
> [6, 'none']
I don't especially call it verbose.
> >>> s[x] # Simpler, clearer, more productive
It's certainly smaller.
But the fatal objection to this is that it is a special case for a very
limited benefit: saving half a dozen characters. List comprehensions are
very flexible:
[float(s[3*i % 2]) for i in x if 3 <= i < 12] # for example...
Your proposal doesn't have anywhere near that flexibility. It simply
duplicates perhaps the most trivial list comp [s[y] for y in x], just to
save a dozen or so characters. Python doesn't treat terseness as that big
a virtue.
Besides, if you want this behaviour, you can add it yourself:
class mylist(list):
# Untested!
def __getitem__(self, index):
if type(index) is list:
return [self[i] for i in index]
return super(mylist, self).__getitem__(index)
list = mylist
The only difference is you have to write:
s = list([1,2,3])
instead of s = [1,2,3].
> To quote a poster at http://www.thescripts.com/forum/thread22741.html,
> "While we are at it, I also don't understand why sequences can't be used
> as indices. Why not, say, l[[2,3]] or l[(2, 3)]? Why a special slice
> concept? " Isn't that unpythonic?
But can't you see that the suggestion to use sequences as replacements
for slices is completely incompatible with your suggestion above?
seq = range(10)
Would you expect seq[[2,6]] to do an index lookup, as you suggested
originally, or a slice? In the first case, it would return [2, 6], but in
the second, it would return [2, 3, 4, 5].
If sequence indices are slices, what does an index of [1, 2, 3, 4] mean?
> 3. When I first
> started using python, I frequently used map, because I didn't want to
> have to learn the additional syntax of list comprehensions, which
> appeared very nonstructured.
It is a slightly more verbose form of standard mathematical set notation.
In case it comes out wrong, the symbol ϵ is supposed to be the symbol for
"element".
"the set of 3x+1 such that x is in (1, 2, 3) if x is odd"
{ 3x+1 : x ϵ (1, 2, 3) if x%2 }
becomes the list comprehension:
[ 3*x+1 for x in (1, 2, 3) if x%2 ]
> # Is this readable?
> b= [x+y for x in vec1 if x>0 for y in vec2 if y>x ]
It is probably pushing the boundaries of how readable a list comp can get
before it should be refactored, but it hasn't crossed over into
unreadability.
> Perhaps a list comprehension syntax more like the rest of python.
I think the great majority Python folks find the list comprehension
syntax to be one of the MOST Pythonic features, not the least.
--
Steven.
More information about the Python-list
mailing list