Pythonic/idiomatic?

S

Seebs

I have an existing hunk of Makefile code:
CPPFLAGS = "$(filter -D* -I* -i* -U*,$(TARGET_CFLAGS))"
For those not familiar with GNU makeisms, this means "assemble a string
which consists of all the words in $(TARGET_CFLAGS) which start with one
of -D, -I, -i, or -U". So if you give it
foo -Ibar baz
it'll say
-Ibar

I have a similar situation in a Python context, and I am wondering
whether this is an idiomatic spelling:

' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

This appears to do the same thing, but is it an idiomatic use of list
comprehensions, or should I be breaking it out into more bits?

You will note that of course, I have carefully made it a one-liner so I
don't have to worry about indentation*.

-s
[*] Kidding, I just thought this seemed like a pretty clear expression.
 
G

geremy condra

I have an existing hunk of Makefile code:
       CPPFLAGS = "$(filter -D* -I* -i* -U*,$(TARGET_CFLAGS))"
For those not familiar with GNU makeisms, this means "assemble a string
which consists of all the words in $(TARGET_CFLAGS) which start with one
of -D, -I, -i, or -U".  So if you give it
       foo -Ibar baz
it'll say
       -Ibar

I have a similar situation in a Python context, and I am wondering
whether this is an idiomatic spelling:

       ' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

This appears to do the same thing, but is it an idiomatic use of list
comprehensions, or should I be breaking it out into more bits?

You will note that of course, I have carefully made it a one-liner so I
don't have to worry about indentation*.

-s
[*] Kidding, I just thought this seemed like a pretty clear expression.

I believe this is correct, but I may be wrong. Try and see.

CPPFLAGS = ' '.join(filter(lambda x: x.startswith(('-D', '-I', '-i',
'-U')), cflags))

Geremy Condra
 
S

Seebs

For this purpose, there is a generator expression syntax
<URL:http://docs.python.org/reference/expressions.html#generator-expressions>,
almost identical to a list comprehension except without the enclosing
brackets.

' '.join(x for x in target_cflags.split() if re.match('^-[DIiU]', x))

Ahh, handy.

I am torn very much on the generator/comprehension syntax, because on the
one hand, I really prefer to have the structure first, but on the other hand,
I can't easily figure out a way to make the syntax work for that.
The regex is less clear for the purpose than I'd prefer. For a simple
???is it a member of this small set???, I'd find it more readable to use a
simple list of the actual strings::
' '.join(
x for x in target_cflags.split()
if x in ['-D', '-I', '-i', '-U'])

The regex is intentionally not anchored with a $, because I'm looking
for "starts with", not "is".
The latter works only in Python with set literals (Python 2.7 or later).

I think we're stuck with backwards compatibility at least as far as 2.4.

No, I'm not kidding. *sigh*

-s
 
T

Tim Chase

' '.join(x for x in target_cflags.split() if re.match('^-[DIiU]', x))

Ahh, handy. ....
The latter works only in Python with set literals (Python
2.7 or later).

I think we're stuck with backwards compatibility at least as
far as 2.4.

No, I'm not kidding. *sigh*

I feel your pain :) At least be glad you don't have to go back
to 2.3 where Ben's suggested generator-syntax isn't available.
The regex is less clear for the purpose than I'd prefer. For a simple
???is it a member of this small set???, I'd find it more readable to use a
simple list of the actual strings::
' '.join(
x for x in target_cflags.split()
if x in ['-D', '-I', '-i', '-U'])

The regex is intentionally not anchored with a $, because I'm looking
for "starts with", not "is".

I suppose you could do

' '.join(
x for x in target_cflags.split()
if x[:2] in ['-D', '-I', '-i', '-U']
)

or

' '.join(
x for x in target_cflags.split()
if x.startswith(('-D', '-I', '-i', '-U'))
)

or even

' '.join(
x for x in target_cflags.split()
if x[:1] == '-' and x[1:2] in 'DIiU'
)

-tkc
 
S

Seebs

Then you don't yet have the ???any??? and ???all??? built-in functions, or the
tuple-of-prefixes feature of ???str.startswith??? either. Bummer.
Eww.

At which point, the Pythonic thing to do is to convince your
organisation to use a version of Python that's at least officially
supported by the PSF :)

Unfortunately, we're selling something to people who will explode if
we tell them to upgrade their RHEL4 systems, so we have to work on those.
(There is some tiny hope that we'll be able to move the baseline to RHEL5
within another two years.)

If it were only a matter of internal use, my job would be orders of
magnitude easier. (I'm maintaining something that intercepts and wraps
large hunks of the standard C library; if you think dealing with
Python 2.4 is a burden, you ain't seen *nothing* compared to that.)

-s
 
A

Arnaud Delobelle

Seebs said:
I have an existing hunk of Makefile code:
CPPFLAGS = "$(filter -D* -I* -i* -U*,$(TARGET_CFLAGS))"
For those not familiar with GNU makeisms, this means "assemble a string
which consists of all the words in $(TARGET_CFLAGS) which start with one
of -D, -I, -i, or -U". So if you give it
foo -Ibar baz
it'll say
-Ibar

I have a similar situation in a Python context, and I am wondering
whether this is an idiomatic spelling:

' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

You can also use the (less favoured) filter:.... return re.compile("^-[%s]" % flags).match
.... '-ifoo -U -Dbaz'
 
P

Peter Otten

Seebs said:
I have an existing hunk of Makefile code:
CPPFLAGS = "$(filter -D* -I* -i* -U*,$(TARGET_CFLAGS))"
For those not familiar with GNU makeisms, this means "assemble a string
which consists of all the words in $(TARGET_CFLAGS) which start with one
of -D, -I, -i, or -U". So if you give it
foo -Ibar baz
it'll say
-Ibar

I have a similar situation in a Python context, and I am wondering
whether this is an idiomatic spelling:

' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

This appears to do the same thing, but is it an idiomatic use of list
comprehensions, or should I be breaking it out into more bits?

You may be able split and match with a single regex, e. g.
cflags = "-Dxxx -D zzz -i- -U42-U7 -i -U"
re.compile(r"-[DIiU]\S*").findall(cflags)
['-Dxxx', '-D', '-i-', '-U42-U7', '-i', '-U']
re.compile(r"-[DIiU]\s*(?:[^-]\S*)?").findall(cflags)
['-Dxxx', '-D zzz', '-i', '-U42-U7', '-i ', '-U']

Peter
 
M

Mark Wooding

Seebs said:
' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

This appears to do the same thing, but is it an idiomatic use of list
comprehensions, or should I be breaking it out into more bits?

It looks OK to me. You say (elsewhere in the thread) that you're stuck
with 2.4 compatibility. I'd personally avoid the regexp, though, and
write this (actually tested with Python 2.4!):

' '.join(i for i in target_cflags.split()
for p in 'DIiU' if i.startswith('-' + p))
You will note that of course, I have carefully made it a one-liner so I
don't have to worry about indentation*.

I failed at that. You have to put up with my indentation.

-- [mdw]
 
J

Jean-Michel Pichavant

Seebs said:
I have an existing hunk of Makefile code:
CPPFLAGS = "$(filter -D* -I* -i* -U*,$(TARGET_CFLAGS))"
For those not familiar with GNU makeisms, this means "assemble a string
which consists of all the words in $(TARGET_CFLAGS) which start with one
of -D, -I, -i, or -U". So if you give it
foo -Ibar baz
it'll say
-Ibar

I have a similar situation in a Python context, and I am wondering
whether this is an idiomatic spelling:

' '.join([x for x in target_cflags.split() if re.match('^-[DIiU]', x)])

This appears to do the same thing, but is it an idiomatic use of list
comprehensions, or should I be breaking it out into more bits?

You will note that of course, I have carefully made it a one-liner so I
don't have to worry about indentation*.

-s
[*] Kidding, I just thought this seemed like a pretty clear expression.
One pythonic way to do it, is to use an option parser.

optparse (or argparse if python > 2.7)

JM
 
S

Seebs

One pythonic way to do it, is to use an option parser.

That seems like massive overkill -- I don't care about any of the other
options. It seems like it'd result in doing more work to get and then
extract the options, and most of that would be discarded instnatly.

-s
 
M

Martin Gregorie

That seems like massive overkill -- I don't care about any of the other
options. It seems like it'd result in doing more work to get and then
extract the options, and most of that would be discarded instnatly.
I've always used an extended version of getopt() in C. I was so surprised
to see that there's nothing equivalent in Java that I wrote my own and
was consequently was very pleased to find that Python already has the
optparse module. Using it is a no-brainer, particularly as it makes quite
a good fist of being self-documenting and of spitting out a nicely
formatted chunk of help text when asked to do so.
 
R

Robert Kern

Unfortunately, we're selling something to people who will explode if
we tell them to upgrade their RHEL4 systems, so we have to work on those.
(There is some tiny hope that we'll be able to move the baseline to RHEL5
within another two years.)

When we deal with such people, we also sell them a recent Python interpreter. :)

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top