tags:

views:

172

answers:

8

The original question was:

Is there a way to declare macros in Python as they are declared in C:

#define OBJWITHSIZE(_x) (sizeof _x)/(sizeof _x[0])

Here's what I'm trying to find out:

Is there a way to avoid code duplication in Python? In one part of a program I'm writing, I have a function:

def replaceProgramFilesPath(filenameBr):
  def getProgramFilesPath():
    import os
    return os.environ.get("PROGRAMFILES") + chr(92)
  return filenameBr.replace("<ProgramFilesPath>",getProgramFilesPath() )

In another part, I've got this code embedded in a string that will later be
output to a python file that will itself be run:

"""
def replaceProgramFilesPath(filenameBr):
  def getProgramFilesPath():
    import os
    return os.environ.get("PROGRAMFILES") + chr(92)
  return filenameBr.replace("<ProgramFilesPath>",getProgramFilesPath() )
"""

How can I build a "macro" that will avoid this duplication?

+3  A: 

No, Python does not support preprocessor macros like C. Your example isn't something you would need to do in Python though; you might consider providing a relevant example so people can suggest a Pythonic way to express what you need.

Greg Hewgill
+2  A: 

While there does seem to be a library for python preprocessing called pypp, I am not entirely familiar with it. There really is no preprocessing capability for python built-in. Python code is translated into byte-code, there are no intermediate steps. If you are a beginner in python I would recommend avoiding pypp entirely.

The closest equivalent of macros might be to define a global function. The python equivalent to your C style macro might be:

import sys
OBJWITHSIZE = lambda x: sys.getsizeof(x) / sys.getsizeof(x[0])
aList = [1, 2, 4, 5]
size = OBJWITHSIZE(aList)
print str(size)

Note that you would rarely ever need to get the size of a python object as all allocation and deletion are handled for you in python unless you are doing something quite strange.

Instead of using a lambda function you could also do this:

import sys
def getSize(x):
   return sys.getsizeof(x) / sys.getsizeof(x[0])

OBJWITHSIZE = getSize
aList = [1, 2, 4, 5]
size = OBJWITHSIZE(aList)
print str(size)

Which is essentially the same.

As it has been previously mentioned, your example macro is redundant in python because you could simply write:

aList = [1, 2, 4, 5]
size = len(aList)
print str(size)
manifest
+1  A: 

You can do much more powerful things than C macros: you can do lisp macros! You will need to use the ast package however, which can transform any python code into another python code (in particular applying macros). It is, as lisp macros, much harder to use than C macros, require more knowledge about the language syntax itself, but they can make wonderful things.

You can see one example of a macro I've made that makes any function traceable: printing all variables when they are set and printing every line before it is executed. The specs go more in details.

Daniel Ribeiro
That's really powerful! I'd wondered about metaprogramming in Python.
Dragos Toader
This is essentially the most powerful metaprogramming technique. Even lisp doesnt have is full power, as Python can do this on runtime, while lisp can't. But python's standard metaprogramming technique is the use of __metaclasses__ (http://www.voidspace.org.uk/python/articles/metaclasses.shtml) and, even more commonly, decorators (http://www.artima.com/weblogs/viewpost.jsp?thread=240808)
Daniel Ribeiro
+2  A: 

This is not supported at the language level. In Python, you'd usually use a normal function or a normal variable where you might use a #define in C.

Mike Graham
A: 

Well, for the brave, there's Metapython:

http://code.google.com/p/metapython/wiki/Tutorial

For instance, the following MetaPython code:

$for i in range(3):
    print $i

will expand to the following Python code:

print 0
print 1
print 2

But if you have just started with Python, you probably won't need it. Just keep practicing the usual dynamic features (duck typing, callable objects, decorators, generators...) and you won't feel any need for C-style macros.

Marco Mariani
+2  A: 

Answering the new question.

In your first python file (called, for example, first.py):

import os

def replaceProgramFilesPath(filenameBr):
  new_path = os.environ.get("PROGRAMFILES") + chr(92)
  return filenameBr.replace("<ProgramFilesPath>", new_path)

In the second python file (called, for example, second.py):

from first import replaceProgramFilesPath
# now replaceProgramFilesPath can be used in this script.

Note that first.py will need to be in python's search path for modules or the same directory as second.py for you to be able to do the import in second.py.

PreludeAndFugue
A: 

You can write this into the second file instead of replicating the code string

"""
from firstFile import replaceProgramFilesPath
"""
gnibbler
+1  A: 

Generally speaking if you want to convert string to python code, use eval. You rarely need eval in Python. There's a module somewhere in the standard library that can tell you a bit about an objects code (doesn't work in the interp), I've never used it directly. You can find stuff on comp.lang.python that explains it.

As to 'C' macros which seem to be the real focus of your question.

clears throat DO NOT USE C MACROS IN PYTHON CODE.

  1. If all you want is a C macro, use the C pre processor to pre process your scripts. Duh.

  2. If you want #include, it's called import.

  3. If you want #define, use an immutable object. Think const int foo=1; instead of #define foo 1. Some objects are immutable, like tuples. You can write a function that makes a variable sufficiently immutable. Search the web for an example. I rather like static classes for some cases like that.

  4. If you want FOO(x, y) ... code ...; learn how to use functions and classes.

Most uses of a 'CPP' macro in Python, can be accomplished by writing a function. You may wish to get a book on higher order functions, in order to handle more complex cases. I personally like a book called Higher Order Perl (HOP), and although it is not Python based, most of the book covers language independent ideas -- and those ideas should be required learning for every programmer.

For all intents and purposes the only use of the C Pre Processor that you need in Python, that isn't quite provided out of box, is the ability to #define constants, which is often the wrong thing to do, even in C and C++.

Now implementing lisp macros in python, in a smart way and actually needing them... clears throat and sweeps under rug.

TerryP
Btw, if you are writing out a python file to then be import'ed some where else in the program, you should probably think about another design, unless you are using a separate python interpreter to run it, or unless that is your programs purpose (writing programs that write programs). In which case of the last, you really should read HOP.
TerryP