13

I was going through the code golf question here on Stack Overflow and saw many Perl one-liner solutions.

Is something like that possible in Python?

brian d foy
  • 129,424
  • 31
  • 207
  • 592
user485167
  • 183
  • 1
  • 5
  • 2
    Yes??? It might be a good idea to precise what you want to do... – Vincent Savard Oct 23 '10 at 20:36
  • 2
    belongs on programmers.stackexchange.com – SilentGhost Oct 23 '10 at 20:37
  • 1
    There are plenty of python one liners with the cods-golf tag. Not as many as perl, but I am surprised you didn't see _any_ of them – John La Rooy Oct 23 '10 at 20:49
  • yes, and it is well implemented to transform any python code to a one-liner up here - https://github.com/csvoss/onelinerizer boom! – Fanglin Jan 26 '18 at 21:14
  • The canonical is (effectively, despite the title): *[How can I put multiple statements in one line?](https://stackoverflow.com/questions/6167127/)*. One [of the answers](https://stackoverflow.com/questions/6167127/how-can-i-put-multiple-statements-in-one-line/6167353#6167353) directly addresses the feasibility of ***one-liners in Python***. – Peter Mortensen Oct 07 '22 at 02:15

8 Answers8

23

python -c 'print("Yes.")'

Daenyth
  • 35,856
  • 13
  • 85
  • 124
17

It's possible to write one liners in Python but it's awkward (Python encourages well indented code which is somewhat at odds with the "one-liner" concept). It's a bit easier in Python 3 because print() is a function and not a statement. Here's one:

python -c "fact = lambda x: x * fact(x-1) if x > 1 else 1; print(fact(5))"

Here's how you could write a grep like function (this example prints lines from input containing "foo"):

python -c "for s in __import__('fileinput').input(): __import__('sys').stdout.write(s) if 'foo' in s else None"
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
10

I end up wanting to do this fairly often when doing stuff from the shell. It doesn't end up being more compact, and in many cases it's easier to just write a multi-line shell command than to write everything as a lambda. You pretty much can't use any Python statement that ends with a colon. So you end up having to

  • write any for-like code as a genexp or list comprehension. I Do this anyway for most stuff, but it's annoying to have to import sys and push everything to sys.stdout.writelines in cases where you could otherwise just

     for tree in forest:
         print tree
    
  • write lambdas instead of function definitions. This is often workable and has the useful side effect of forcing you to write very directed functions that really only do one thing. However, it's not particularly convenient, and doesn't work for anything that mutates a value (e.g., dict.update) and then returns some element.

  • Do not bother doing things properly with context managers

  • Do not do any exception handling.

  • Use a dictionary of lambdas instead of any if/else sections.

  • Use type(name, bases, dict) to declare any classes. This is pretty fun but only works if you happen to be declaring a class whose methods can all be expressed as lambdas.

So for some things it works out but generally it's a big hassle, because you end up having to use a functional style that Python doesn't really support. Most of the time I just write multiline shell commands like

python -c $'
import some_module
for v in some_module.whatever():
    print "Whatever: \'{0}\'".format(v)
'

The $' is a bash quoting syntax, an alternative to its '...' and "..." quoting constructs. It's useful, because it works like '...', but let’s you escape contained ' characters with \'. You can also embed newlines, so the above code could also be written as python -c $'import some_module\nfor v in some_module.whatever():\n print "Whatever: \'{0}\'".format(v)'. However, this is something of an acquired taste.

One annoying thing about writing multiline commands in bash is that HOME and END go to the beginning of the command rather than the beginning of the line. There may be a better way to do this, but I usually just scan back and forth by holding down CTRL and the left/right arrow keys. Some Emacs user could probably set me straight here, since that's where bash's normal key bindings come from.

If you want to insert a line break while editing a multiline command, you can do this with ^V-^J. That will put in a line break in such a way that you can still scan back to the previous lines, rather than using the

$ first line of the command
> second line
> third line

setup that you get otherwise, where you can't get back to the previous lines.

The trick with ^V-^J works in IPython too, making it useful for editing class or function definitions. It may also work in the basic Python REPL (probably); I just don't know, because I nearly always use IPython.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
intuited
  • 23,174
  • 7
  • 66
  • 88
4

In Bourne shell you can use something called heredoc to get around Python's dependency on indents:

python << 'EOF'
> for i in range(3):
>  print i
> EOF
0
1
2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
S010
  • 41
  • 2
  • 2
    no you cant. you indented `print`. Try it without indenting it and you get an `IndentationError` just like you're supposed to. – aaronasterling Oct 23 '10 at 21:01
  • 1
    I phrased it wrong. This gives you the ability to indent code, without actually having to create a file, open editor, etc. – S010 Oct 23 '10 at 21:09
  • There isn't really such a thing as "getting around" the "dependency on indents" for python since it would make it impossible to write most nontrivial programs. What most readers are after is how to indicate the indent/dedents in a one-liner way. – Steven Lu Sep 22 '13 at 18:42
  • 1
    You probably just mean "to *satisfy* Python's dependency on indents." – Ken Williams Sep 07 '18 at 02:43
2

A really nice Python one-liner (as in "quite useful"):

python -c 'import SimpleHTTPServer as foo; foo.test()'  23433

It creates an instant basic web server in the current directory. (I was just introduced to this today, and it is very handy.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joe McMahon
  • 3,266
  • 21
  • 33
0

Here is my trick to run multiple statements:

[stmt1, stmt2, expr1][2] if requires lazy evaluation: [lambda(): stmt1; lambda(): stmt2][not not boolExpr]()

Ming-Tang
  • 17,410
  • 8
  • 38
  • 76
0
exec("if 6 * 9 == int('42', 13):\n\tprint('Yes!')")

With this approach, every Python program can be written as a one-liner :)

dan04
  • 87,747
  • 23
  • 163
  • 198
-2

Yes, actually it is very common. I use one-liners when I need to write quick code. It just depends on what you want to do. Here is a small line I just used this evening. It is the creation of a Tkinter button in a single line.

a = Button(root, text="Button", command=com1).pack()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zac Brown
  • 5,905
  • 19
  • 59
  • 107