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

print a ... z, A ... Z, "\n"' in Python

P: n/a
js
HI guys,

How do you write Perl's

print a ... z, A ... Z, "\n"' in Python
In Python?
A way I came up with is the following, but I'm sure this is ugly.

''.join(chr(c) for c in (range(ord('a'), ord('z')+1) +
range(ord('A'), ord('Z')+1)))
or
crange = lambda c1, c2: [ chr(c) for c in range(ord(c1), ord(c2)+1) ]
''.join(chr(c) for c in crange('a', 'z') + crange('A', 'Z'))
I want to feel The Zen of Python :)
Mar 3 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
js:
crange = lambda c1, c2: [ chr(c) for c in range(ord(c1), ord(c2)+1) ]
''.join(chr(c) for c in crange('a', 'z') + crange('A', 'Z'))
Yes, managing char ranges is a bit of pain with Python.
You can also pack those chars:

xcrange = lambda cc: (chr(c) for c in xrange(ord(cc[0]), ord(cc[1])
+1))

But I don't like that much.

The calls:
''.join(xcrange('az')) + ''.join(xcrange('AZ'))

But note that you return the last item of the range too, and that goes
against the semantic of the usual Python range/xrange, so you may want
to call this function with another name.

Maybe there are better ways to solve this problem. Maybe a way to
generate (closed?) char ranges can be added to the Python standard
lib.

Bye,
bearophile

Mar 3 '07 #2

P: n/a
js
But note that you return the last item of the range too, and that goes
against the semantic of the usual Python range/xrange, so you may want
to call this function with another name.
That makes sense. 100% agree with you.
Maybe there are better ways to solve this problem. Maybe a way to
generate (closed?) char ranges can be added to the Python standard
lib.
Maybe we don't want char range If string constants would be rich enough.
Mar 3 '07 #3

P: n/a

js wrote:
A way I came up with is the following, but I'm sure this is ugly.
You could abuse __getitem__ (terribly, heh!) and use slice syntax...

class crange():
def __init__(self):
self.valid = range(47,58) + range(65,91) + range(97,123)
def __getitem__(self, s):
if isinstance(s, slice):
start, stop = s.start, s.stop
if not start: start = '0'
if isinstance(stop, int) and stop 122: stop = 'z'
elif not stop: stop = 'z'
clist = []
chars = range(ord(start), ord(stop)+1)
for i in range(len(chars)):
if chars[i] in self.valid:
clist.append(chr(chars[i]))
return ''.join(clist)
else:
return s

cr = crange()
print cr['A':'z']
print cr['0':'8']
print cr[:]

Regards,
Jordan

Mar 3 '07 #4

P: n/a
"js " <eb*****@gmail.comwrites:
>But note that you return the last item of the range too, and that
goes against the semantic of the usual Python range/xrange, so you
may want to call this function with another name.

That makes sense. 100% agree with you.
>Maybe there are better ways to solve this problem. Maybe a way to
generate (closed?) char ranges can be added to the Python standard
lib.

Maybe we don't want char range If string constants would be rich
enough.
But as soon as we want a string that doesn't correspond to any
pre-defined constants, we're hosed. For example, there isn't
a constant that would correspond to this Perl-ism:

print l ... w, e ... j, L ... W, E ... J, "\n";
--
Lloyd Zusman
lj*@asfast.com
God bless you.

Mar 3 '07 #5

P: n/a
js
Maybe we don't want char range If string constants would be rich
enough.

But as soon as we want a string that doesn't correspond to any
pre-defined constants, we're hosed. For example, there isn't
a constant that would correspond to this Perl-ism:

print l ... w, e ... j, L ... W, E ... J, "\n";
Yes, I'm certain that l ... w, e ..j will never be a constant
because that doesn't mean a thing so nobody want them :)
Mar 3 '07 #6

P: n/a
js <eb*****@gmail.comwrote:
HI guys,

How do you write Perl's

print a ... z, A ... Z, "\n"' in Python

In Python?
This specific one is easy, though this doesn't generalize:

import string
print string.lowercase + string.uppercase

For the general case, there's no way to avoid calling chr and ord,
because a string in Python doesn't have a "natural successor". So the
only issue is how you prefer to hide those calls &c (in some class or
function) and you already received suggestions on that.
Alex
Mar 3 '07 #7

P: n/a
al***@mac.com (Alex Martelli) wrote in
news:1hue4db.1ifwnsjmhm2pN%al***@mac.com:
js <eb*****@gmail.comwrote:
>HI guys,

How do you write Perl's

print a ... z, A ... Z, "\n"' in Python

In Python?

This specific one is easy, though this doesn't generalize:

import string
print string.lowercase + string.uppercase

For the general case, there's no way to avoid calling chr and
ord, because a string in Python doesn't have a "natural
successor". So the only issue is how you prefer to hide those
calls &c (in some class or function) and you already received
suggestions on that.
No ord or chr in sight:

# Inclusive character range.
def pycrange(lo,hi):
import string
chars = string.letters + " "
rstr = ''
lp = chars.find(lo)
hp = chars.find(hi)
if lp < hp:
rstr = chars[lp:hp+1]
return rstr

print pycrange('c','n')
Lame code, though.

--
rzed
Mar 3 '07 #8

P: n/a
rzed <rz*****@gmail.comwrote:
al***@mac.com (Alex Martelli) wrote in
news:1hue4db.1ifwnsjmhm2pN%al***@mac.com:
js <eb*****@gmail.comwrote:
HI guys,

How do you write Perl's

print a ... z, A ... Z, "\n"' in Python

In Python?
This specific one is easy, though this doesn't generalize:

import string
print string.lowercase + string.uppercase

For the general case, there's no way to avoid calling chr and
ord, because a string in Python doesn't have a "natural
successor". So the only issue is how you prefer to hide those
calls &c (in some class or function) and you already received
suggestions on that.

No ord or chr in sight:

# Inclusive character range.
def pycrange(lo,hi):
import string
chars = string.letters + " "
rstr = ''
lp = chars.find(lo)
hp = chars.find(hi)
if lp < hp:
rstr = chars[lp:hp+1]
return rstr

print pycrange('c','n')
Lame code, though.
Very (the very existence of rstr and the if block are redundant, for
example; "return chars[lp:hp+1]" will already return an empty string
when lp hp, and it's weird for the result to be empty for equal
arguments lo and hi when it's a length-two string for arguments, say,
'a' and 'b').

Also incorrect, presumably, since it would e.g. consider pycrange('w',
'C') to be 'wxyzABC', rather than empty (as an ord/chr based solution
would) or 'wxyz' (as I believe Perl does for 'w'...'C' -- one of those
black-magical Perl things, unless they've changed it recently) -- in
ASCII, uppercase letters come before lowercase ones, but in
string.letters they're vice versa.

Sure, you can get a complete 256-char ASCII alphabet with
alp=string.maketrans('', ''), use alp.find(x) as roughly equivalent to
ord(x) and alp[y] as roughly equivalent to chr(y), and thus (or by
sillier tricks yet) you wouldn't _formally_ "be calling chr and ord"
(you'd instead use roughly equivalent but slower and murkier idioms).
However, my point was: you can't avoid transforming from characters to
numbers and back again (ord and chr are just the "one obvious way" to do
that -- correct, if you want ASCII, readable, direct, and fast). .find
and indexing (instead of ord and chr) do give you more flexibility (to
use an underlying order that's not ASCII's) should you need that; and
slicing an appropriate string does avoid an explicit loop.

(Just trying to forestall further silliness...): other ways to avoid
"calling chr and ord" include abusing modules struct and array.
Alex
Mar 4 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.