Is there a better way of doing this?

M

Michael

Hi,
I'm fairly new at Python, and have the following code that works but isn't
very concise, is there a better way of writing it?? It seems much more
lengthy than python code i have read..... :)
(takes a C++ block and extracts the namespaces from it)



def ExtractNamespaces(data):
print("Extracting Namespaces")
p = re.compile( 'namespace (?P<name>[\w]*)[\n\t ]*{')

subNamespaces = []

newNS = p.search(data)
while( newNS ):
print "\t" + newNS.group("name")

OPCount = 1
Offset = newNS.end()
while(OPCount > 0):
if( data[Offset] == "}" ):
OPCount = OPCount -1;
elif( data[Offset] == "{" ):
OPCount = OPCount + 1;
Offset = Offset+1;

#Extract Data:
newNSData = data[newNS.end():Offset-1]
data = data[0:newNS.start()] + data[Offset:]
newNamespace = [newNS.group("name"), newNSData];
subNamespaces.append(newNamespace)

#Perform NewSearch
newNS = p.search(data)
return [subNamespaces,data]
 
S

Steven D'Aprano

Hi,
I'm fairly new at Python, and have the following code that works but isn't
very concise, is there a better way of writing it?? It seems much more
lengthy than python code i have read..... :)
(takes a C++ block and extracts the namespaces from it)


Does it work? If Yes, then "if it works, don't fix it".

Is it fast enough? If Yes, then "don't optimise prematurely".

Does it do everything you need it to do? If Yes, then "know when to stop
programming".

Is it written in good Python style? If Yes, then "leave it alone".

The last one is the most difficult, because nobody agrees what good
Python style is. A lot of it depends on who is going to be reading your
code. Personally, I worry about folks who try to turn every piece of code
into a one-liner. If you want to write perl, write perl. Just because you
can write something as a nested list comprehension doesn't mean you should.

Having said that, I'll make some stylistic suggestions:
def ExtractNamespaces(data):
print("Extracting Namespaces")

print is a statement, not a function. The brackets are syntactically
correct, but pointless. Remove them.
p = re.compile( 'namespace (?P<name>[\w]*)[\n\t ]*{')

subNamespaces = []

newNS = p.search(data)
while( newNS ):

Guido (our Benevolent Dictator For Life and creator of Python) hates
seeing whitespace next to parentheses. I agree with him. while(newNS)
good, while( newNS ) bad.

See http://www.python.org/doc/essays/styleguide.html for Guido's
suggestions.
print "\t" + newNS.group("name")

OPCount = 1
Offset = newNS.end()
while(OPCount > 0):
if( data[Offset] == "}" ):

See above comment about whitespace inside brackets.

More importantly, you don't need the brackets at all. You can write:

if data[Offset] == "}":

which is less visually confusing. The only time I use brackets in an if
statement is to clarify complex Boolean expressions, eg

if myFlag and ((somevalue == 3) or (num_fibberts != 1)):

Otherwise, drop the brackets.
OPCount = OPCount -1;

You aren't writing Pascal or C now, so you don't need the semi-colon. The
semi-colon isn't wrong, as such, since Python allows you to put multiple
statements on a single line separated with semi-colons, but it isn't
recommended and will give away the fact that you are (1) a newbie and (2)
not really comfortable with Python.

In more recent versions of Python, you can also write that as OPCount -= 1
elif( data[Offset] == "{" ):
OPCount = OPCount + 1;
Offset = Offset+1;

Again, drop the brackets from the elif statement and the semi-colons. Not
the colons, they are required!
#Extract Data:

More comments! Comments are good. There are those who claim that you
should write more comments than code. I don't quite agree with that, but
more detailed comments would not go astray.
newNSData = data[newNS.end():Offset-1]
data = data[0:newNS.start()] + data[Offset:]
newNamespace = [newNS.group("name"), newNSData];
subNamespaces.append(newNamespace)

By now you should be sick of me telling you not to use semi-colons.
#Perform NewSearch
newNS = p.search(data)
return [subNamespaces,data]

A single space after commas helps make the phrase more readable.

Other than those stylistic comments, and the need for more comments, it
looks good to me.
 
F

Fredrik Lundh

Steven said:
Guido (our Benevolent Dictator For Life and creator of Python) hates
seeing whitespace next to parentheses. I agree with him. while(newNS)
good, while( newNS ) bad.

while is a statement, so while(newNS) is bad in more than one way.

</F>
 
R

Roman Yakovenko

Hi,

I don't know very well what you want to do, but if you want to parse c++,
take a look at "GCC-XML python" (http://www.gccxml.org) and the python
binding (http://pygccxml.sourceforge.net/). These tools
translate c++ code to XML. Then, you can parse xml with your favorite tools
and find the namespaces for example...

Small correction: pygccxml does not translate C++ to xml. The purpose
of pygccxml is to read file generated by GCC-XML and provide simple
framework to navigate C++ declarations using python classes.

Roman
 
D

Duncan Booth

Michael said:
I'm fairly new at Python, and have the following code that works but
isn't very concise, is there a better way of writing it?? It seems
much more lengthy than python code i have read..... :)
(takes a C++ block and extracts the namespaces from it)

Yes, there is a better way to write the code, but I'm afraid that the
better way will be much longer rather than shorter. Your code is trying to
pick up a complete C++ block by counting the opening and closing braces,
but this will break as soon as you have a brace character inside a string
or a comment.

The better solution would be to use a full blown parser, or at least a
lexer which recognises comments and strings. There are several parsing
packages for Python, you might like to look at Ply
(http://www.dabeaz.com/ply/) since that comes with a sample lexer for Ansi
C, and if you added some extra keywords (such as namespace) you could then
just treat your input as a token stream.
 
M

Magnus Lycka

Steven said:
> print is a statement, not a function. The brackets are syntactically
> correct, but pointless. Remove them. ....


Guido (our Benevolent Dictator For Life and creator of Python) hates
seeing whitespace next to parentheses. I agree with him. while(newNS)
good, while( newNS ) bad.

while is a statement, not a function. The brackets are syntactically
correct, but pointless. Remove them. ;^)

while newNS:

Not only are they pointless (in both print and while), but they are
blurring the distinction between statements and callables, and they
add noise. Only wrap the expression following a statement such as
while, if, print etc in () if the following expression spans several
lines.

Using () instead of \ as line continuator is considered good style.
(See http://www.python.org/doc/essays/ppt/regrets/PythonRegrets.pdf
slide 3.) In that case, make sure you have a space between the
statement and the (. Never have space between a callable and
the (. That way, we emphasize the difference between a statemens
and a call. E.g:

while (aVeryVeryVeryLongVariableName == anotherVeryVeryLongName
or aThirdLongVariableName == aFourthLongVariableName):
something = function(parameterOne, parameterTwo, parameterThree,
parameterFour, parameterFive, etc)


N.B. Use "while (" but "function(".

(I'm not suggesting that such long variable names are generally
good, but there are certainly cases where both logical expressions
and parameter lists will be too long for one line, for instance when
working with stuff such as the win32 APIs.)

Please note the big conceptual difference in using a statement which
controls local program flow, and calling a function/method/class etc
which means that we transfer control to a different part of the
program. Some of the current statements in Python, e.g. print,
actually behaves more like a function than like the normal statements,
and this might be considered a wart. It's also mentioned in Guido's
"regrets" slides mentioned above. Print and exec *are* still not
callables though. They *are* statements, whether we like it or not.

If writing "print(something)" feels better than "print something",
I suggest you define a function called writeln etc and use that
instead of print, e.g.
.... sys.stdout.write(" ".join(map(str, args)) + '\n')
 
S

Steven D'Aprano

while is a statement, not a function. The brackets are syntactically
correct, but pointless. Remove them. ;^)

Um. Er.

Of course I knew that. I deliberately made that error to see if others
were paying attention. Well done, go to the head of the class. *cough*

:)

while newNS:

Not only are they pointless (in both print and while), but they are
blurring the distinction between statements and callables, and they
add noise. Only wrap the expression following a statement such as
while, if, print etc in () if the following expression spans several
lines.

Yes, of course you are right. Serves me right for replying to Usenet posts
in the wee hours of the morning.

Although, pardon me for stating the obvious, using brackets for
precedence, or to add clarity by careful grouping, is always allowed even
if the expression doesn't span more than one line.

eg while (index > 0) and (not found or still_working):
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top