do python's nifty indentation rules spell the death of one-liners?

Carl Banks imbosol-1050452170 at aerojockey.com
Tue Apr 15 20:45:33 EDT 2003


Dan Jacobson wrote:
> I need to use one liners every day, especially in Makefiles.  I thus
> need to know how to make any kind of python program into a big long one
> liner. However, right out of the starting gates I run into
> $ python -c 'print 2;for i in (1,4):print i'
>  File "<string>", line 1
>    print 2;for i in (1,4):print i
>              ^
> SyntaxError: invalid syntax
> 
> Help. BTW tell me what to do in all the other cases when ";" can't be
> a replacement for newline.  I.e. does python's nifty indentation rules
> spell the death of one-liners?

That can be a problem.  I can understand why it might be a pain to
litter your directory with little Python scripts.

You can work around most little problems if there is only one loop.
Stuff that comes before the loop would have to be folded into the loop
somehow.  See below.


> BTW, how do I import a module from the command line when using -c? Is
> there an option switch for importing modules?
> 
> This makes no output and returns no error value to the shell:
> $ python -c 'import math' -c 'for i in range(200,500,50): print
>  i,360/2/math.pi*math.asin(i/1238.4)'


The most common thing you want to put before a loop is import.  The
workaround is to import the module inside the loop with __import__:

python -c 'for i in range(200,500,50): print i,360/2/__import__("math").pi\
*__import__("math").asin(i/1238.4)'


Another thing you might want to do before the loop is set a variable,
like this:

    a=1; for i in range(20): a = complicated_function(a)

You can set the global inside the loop with the following trick:

python -c 'for i in range(20): globals("a").setdefault(1); \
a = complicated_function(a)'


Sometimes you want to print something before the first loop.  You can
work around this using the short-circuiting "and" operator to test
whether you're on the first iteration, along with the import trick
above and sys.stdout, like this:

python -c 'for i in range(20): i==0 and __import__("sys").stdout.\
write("Hello.\n"); do_whatever()'


You can simulate a nested loop with a list comprehension.  For
example, if you wanted to do something like this in one line:

    for i in range(10):
        for j in range(10):
            do_whatever(i,j)

You can do this:

python -c 'for (i,j) in [ (i,j) for i in range(10) for j in range(10) ]:\
do_whatever(i,j)'


What you can do in one line of Python code is surprising, if you know
all kinds of little workarounds like this.

The best thing to do might be to find a preprocessor that'll accept
Python code with braces, and feed it to Python in indented form.  Or
just litter your directories with scripts.



-- 
CARL BANKS




More information about the Python-list mailing list