183

I know a little bit of comprehensions in Python, but they seem very hard to 'read'. The way I see it, a comprehension might accomplish the same as the following code:

for i in range(10): if i == 9: print('i equals 9')

This code is much easier to read than how comprehensions currently work, but I've noticed you can’t have two :s in one line. This brings me to:

Is there a way I can get the following example into one line?

try:
    if sam[0] != 'harry':
        print('hello',  sam)
except:
    pass

Something like this would be great:

try: if sam[0] != 'harry': print('hellp',  sam)
except:pass

But again I encounter the conflicting :s.

I'd also love to know if there's a way to run try (or something like it) without except. It seems entirely pointless that I need to put except:pass in there. It’s a wasted line.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rhys
  • 4,926
  • 14
  • 41
  • 64
  • Why would it ever throw an exception? – Ignacio Vazquez-Abrams May 29 '11 at 10:15
  • 3
    sam[2] may not exist. It's a hypothetical example. thanks – Rhys May 29 '11 at 10:19
  • 5
    Comprehension is something different in Python. Putting everything in one line is not comprehension. – Felix Kling May 29 '11 at 10:20
  • I am aware of this yes. thanks. I was just demonstrating how i think comprehension might work better but can't due to the colon which is the root of my problem/question – Rhys May 29 '11 at 10:21
  • Just use `\n`s and use spaces for indents. –  Jun 26 '17 at 03:45
  • Sidenote, [a bare `except` is bad practice](https://stackoverflow.com/q/54948548/4518341), especially where you're not doing anything to handle it. – wjandrea Jan 20 '21 at 16:49
  • Python does support single line see [answer May 29, 2011 at 11:00](https://stackoverflow.com/a/6167353/6345724) ... BUT. Most standard code blocks do not support single line. Code author needs to find a `lambda` equivalent. Examples: `try` alternative(s) `with contextlib.suppress(Exception): {code}` `if` alternative(s) `{true code} if {boolean result} else {false code}` (software: Python3) – dank8 Sep 25 '22 at 03:14
  • Note: [A late answer](https://stackoverflow.com/questions/6167127/how-can-i-put-multiple-statements-in-one-line/24451002#24451002) (3 years after), seems to indicate one-liners, ***incl. control structures***, are indeed possible in Python. – Peter Mortensen Oct 07 '22 at 10:50

15 Answers15

187

Unfortunately, what you want is not possible with Python (which makes Python close to useless for command-line one-liner programs). Even explicit use of parentheses does not avoid the syntax exception. You can get away with a sequence of simple statements, separated by semicolon:

for i in range(10): print "foo"; print "bar"

But as soon as you add a construct that introduces an indented block (like if), you need the line break. Also,

for i in range(10): print "i equals 9" if i==9 else None

is legal and might approximate what you want.

If you are still determined to use one-liners, see the answer by elecprog.

As for the try ... except thing: It would be totally useless without the except. try says "I want to run this code, but it might throw an exception". If you don't care about the exception, leave out the try. But as soon as you put it in, you're saying "I want to handle a potential exception". The pass then says you wish to not handle it specifically. But that means your code will continue running, which it wouldn't otherwise.

ThomasH
  • 22,276
  • 13
  • 61
  • 62
  • 1
    interesting, i think your latter example comes closest to the answer I was looking for. thanks – Rhys May 29 '11 at 20:04
  • with regards to the 'try' question ... What If, I know at some point it is going to throw an exception but I just want the code to continue running ... for instance, to check if a string can be an integer try: int(string) ... If it can't, then just continue to the next line, no need for an exception. I see what you're saying, but is there any other way that can accommodate for this type of checking/error-handling – Rhys May 29 '11 at 20:13
  • 6
    Re ``try:``: The Python syntax rules simply won't let you get away with a sole "try" clause without accompanying "except" clause. What I do is wrapping the try-except in on own function, and call this instead. Like ``if (checkint(s))...`` and ``def checkint(s): try: int(s)\nreturn True\nexcept: return False``. – ThomasH May 29 '11 at 21:01
  • 1
    ThomasH, I wish your comment were an answer to a question somewhere so I could upvote it. Excellent. – Ivan X Mar 29 '15 at 17:39
  • @ThomasH When you put `pass` in except you _are_ saying you wish to handle the exception specifically -- by doing nothing! `except: pass` is a dangerous design move IMO, as it will probably hide errors one didn't expect. Better to drop the try/except, list specific exceptions you expect, or improve your design and code to avoid errors! – jtpereyda Jul 15 '15 at 17:33
  • 8
    @ThomasH "*(which makes Python close to useless for command-line one-liner programs)*" : does not hinder me. 95% cases need no new-line. And the rest via \n : `python -c "exec\"print 'A' \nfor i in 1,2,3: print i \""` – kxr Feb 26 '16 at 09:24
  • Downvoted because: No answer to the question plus language bashing. – Torsten Bronger Aug 12 '18 at 08:46
  • @kxr - Not working for me... can't see what I am doing wrong. `python2.7 -c "import ssl\nprint ssl.OPENSSL_VERSION"` gives `SyntaxError: unexpected character after line continuation character`. I had to do this (which is getting a bit hairy and probably won't render properly in a comment): `python2.7 -c "\`printf 'import ssl\nprint ssl.OPENSSL_VERSION'\`"` – user9645 Oct 08 '19 at 11:51
  • @ThomasH can i do the second line without else? – Joshua Varghese Apr 17 '20 at 09:52
  • 1
    @JoshuaVarghese No, I'm afraid Python's [Conditional Expression](https://docs.python.org/3/reference/expressions.html#conditional-expressions) can only be used with the `else` (prob. b/c it's an expression and not a statement). – ThomasH Apr 18 '20 at 11:44
  • When i give the else as None, sometimes values become none. also in one-liners, is it possible to do liner `[i for i in list1 if i not (here in this list]` ??? – Joshua Varghese Apr 18 '20 at 11:46
  • 1
    @JoshuaVarghese Yes, because the Condtional Expression always returns a value, either from the false or the true case. And yes, you can use List Comprehension in one-liners, but mind that the `if` in a list comprehension is not the `if` of a Conditional Expression. It pertains to the list comprehension syntax itself, and here no `else` is allowed: `python -c "print([i for i in range(10) if i==9])` (using Python3 syntax). You can easily find that out by trying. – ThomasH Apr 18 '20 at 12:03
  • i wanted like if i not in this present list which is being comprehensed – Joshua Varghese Apr 18 '20 at 12:12
  • Mh, you want to avoid duplicates in the result? I'm not sure this is possible, but that's a question on its own, right?! You might want to ask that here on SO. – ThomasH Apr 18 '20 at 12:20
  • @ThomasH it is here https://stackoverflow.com/questions/61290039/how-to-access-the-current-list-that-is-being-comprehensed – Joshua Varghese Apr 18 '20 at 14:07
  • @ThomasH but it happened as i feared. it got downvoted :( – Joshua Varghese Apr 18 '20 at 14:08
  • 3
    @TorstenBronger This does answer the question, and the language bashes itself by not having the capacity. You're shooting the messenger. – WestCoastProjects Nov 10 '21 at 01:39
  • 1
    So, alas, python may be one of the few programming languages that are affected by terminal width. Programmer A with a wide terminal might write highly nested great programs, but Programmer B with not so wide a terminal would find they are no longer on an equal playing field... – Dan Jacobson Nov 14 '21 at 03:50
  • A [later answer](https://stackoverflow.com/questions/6167127/how-can-i-put-multiple-statements-in-one-line/24451002#24451002) seems to contradict. Perhaps address that in your answer? (But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today (how this came to be is not of interest to most readers).) – Peter Mortensen Oct 08 '22 at 21:52
  • @PeterMortensen I'm aware of the issues with legacy answers, and would only use "Edit" or "Update" paragraphs when I retain the old answer (e.g. when it still applies to an older version of the software). – ThomasH Oct 10 '22 at 12:16
  • @DanJacobson, "highly nested great programs" is an oxymoron. :-P – Richard II May 31 '23 at 13:26
73

You could use the built-in exec statement, eg.:

exec("try: \n \t if sam[0] != 'harry': \n \t\t print('hello',  sam) \nexcept: pass")

Where \n is a newline and \t is used as indentation (a tab).
Also, you should count the spaces you use, so your indentation matches exactly.

However, as all the other answers already said, this is of course only to be used when you really have to put it on one line.

exec is quite a dangerous statement (especially when building a webapp) since it allows execution of arbitrary Python code.

eprovst
  • 839
  • 7
  • 8
  • 6
    Thank you! This should be marked as the correct answer, as it actually works, unlike the others. But of course, **never** do this unless you have to! I actually need this syntax however, as I have to input scripts into a fixed one-line text-box. – Sanjay Manohar Aug 21 '14 at 00:49
  • Thanks ! Lifesaver ! I don't use this in my script, but in the interactive shell this is useful for debugging... I often simply quit the interactive shell and restart it to get a clean environment and then I have to repeat certain steps, i.e. importing a module, running some functions and then do some test with a specific function. Soooo, I was looking for a way to put "importing a module, running some functions" in a oneliner, so I can quickly call it back from the history and run it (instead of having to call back 5 different items from the history) +1 – oneindelijk Jan 28 '16 at 06:50
  • `exec("try: \n if sam[0] != 'harry': print('hello', sam) \nexcept: pass")` nicer :) – kxr Feb 26 '16 at 09:17
  • Thank you kxr :) (I used your idea to improve the answer) – eprovst Feb 28 '16 at 10:47
26

You can now just use semicolons. However, you cannot use if/elif/else statements, for/while loops, and you can't define functions. The main use of this would be when using imported modules where you don't have to define any functions or use any if/elif/else/for/while statements/loops.

Here's an example that takes the artist of a song, the song name, and searches genius for the lyrics:

import bs4, requests; song = input('Input artist then song name\n'); print(bs4.BeautifulSoup(requests.get(f'https://genius.com/{song.replace(" ", "-")}-lyrics').text,'html.parser').select('.lyrics')[0].text.strip())
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
NullableMoh
  • 280
  • 3
  • 4
11

I do not incentivise this, but say you're on the command line, you have nothing but Python and you really need a one-liner, you can do this:

python -c "$(echo -e "a=True\nif a : print(1)")"

Here we're pre-processing \n before evaluating Python code.

That's super hacky! Don't write code like this.

Tiago Lopo
  • 7,619
  • 1
  • 30
  • 51
9

For a python -c oriented solution, and provided you use Bash shell, yes you can have a simple one-line syntax like in this example:

Suppose you would like to do something like this (very similar to your sample, including except: pass instruction):

python -c  "from __future__ import print_function\ntry: import numpy; print( numpy.get_include(), end='\n' )\nexcept:pass\n" OUTPUT_VARIABLE __numpy_path

This will not work and produce this error:

  File "<string>", line 1
    from __future__ import print_function\ntry: import numpy; print( numpy.get_include(), end='\n' )\nexcept:pass\n
                                                                                                                  ^
SyntaxError: unexpected character after line continuation character `

This is because the competition between Bash and Python interpretation of \n escape sequences. To solve the problem one can use the $'string' Bash syntax to force \n Bash interpretation before the Python one.

To make the example more challenging, I added a typical Python end=..\n.. specification in the Python print call: at the end you will be able to get both \n interpretations from Bash and Python working together, each on its piece of text of concern. So that finally the proper solution is like this:

python -c  $'from __future__ import print_function\ntry:\n import numpy;\n print( numpy.get_include(), end="\\n" )\n print( "Hello" )\nexcept:pass\n' OUTPUT_VARIABLE __numpy_path

That leads to the proper clean output without an error:

/Softs/anaconda/lib/python3.7/site-packages/numpy/core/include
Hello

Note: this should work as well with exec-oriented solutions, because the problem is still the same (Bash and Python interpreters competition).

Note 2: one could work around the problem by replacing some \n by some ; but it will not work anytime (depending on Python constructs), while my solution allows to always "one-line" any piece of classic multi-line Python program.

Note 3: of course, when one-lining, one has always to take care of Python spaces and indentation, because in fact we are not strictly "one-lining" here, but doing a proper mixed-management of \n escape sequence between bash and Python. This is how we can deal with any piece of classic multi-line Python program. The solution sample illustrates this as well.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pierre13fr
  • 181
  • 2
  • 3
8

I recommend not doing this...

What you are describing is not a comprehension.

PEP 8 Style Guide for Python Code, which I do recommend, has this to say on compound statements:

  • Compound statements (multiple statements on the same line) are generally discouraged.

Yes:

      if foo == 'blah':
          do_blah_thing()
      do_one()
      do_two()
      do_three()

Rather not:

      if foo == 'blah': do_blah_thing()
      do_one(); do_two(); do_three()

Here is a sample comprehension to make the distinction:

>>> [i for i in xrange(10) if i == 9]
[9]
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
3

It’s actually possible ;-)

# Not PEP 8 compatible^
sam = ['Sam',]
try: print('hello', sam) if sam[0] != 'harry' else rais
except: pass

You can do very ugly stuff in Python like:

def o(s):return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or 'N' > n else -13)) if n.isalpha() else n for n in s])

which is a function for ROT13 and Caesar encryption in one line.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yamm
  • 1,523
  • 1
  • 15
  • 25
1

Maybe with "and" or "or".

After false, we need to write "or".

After true we need to write "and".

Like

n = 0

def returnsfalse():
    global n
    n = n + 1
    print("false %d" % (n))
    return False

def returnstrue():
    global n
    n = n + 1
    print("true %d" % (n))
    return True

n = 0
returnsfalse() or returnsfalse() or returnsfalse() or returnstrue() and returnsfalse()

Result:

false 1
false 2
false 3
true 4
false 5

Or maybe like

(returnsfalse() or true) and (returnstrue() or true) and ...

I got here by searching Google with "how to put multiple statments in one line Python". It does not answer the question directly, but maybe somebody else needs this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shimon Doodkin
  • 4,310
  • 34
  • 37
1

If you want it without try and except, then there is the solution.

If you are trying to print 'hello' if 'harry' in a list then the solution is:

'hello' if 'harry' in sam else ''
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ishaant
  • 461
  • 2
  • 3
1

There is a possible PEP 8 compatible solution.

Solution to if, else

[print("i equals 9") for i in range(10) if i == 9]

Use a list generation instead of if, else.

I think this is probably a useful trick, which has already stated by comment by ThomasH. So this is a serious solution.

Solution to try, except

print("hello", sam) \
    if "sam" in locals() \
    and hasattr(sam, "__getitem__") \
    and 0 < len(sam) \
    and sam[0] != "harry" \
    else None

Try to deal with how expect would behave by an in-line if statement. This line of code is specialized to deal with the existence of sam[0], thus I couldn't resolve other general try, except cases.

This is one line of code (=w=). Though if written in exactly one-line, it could be too long to contradict PEP 8 E501. So this is a solution for fun.

  • "sam" in locals checks if sam is a valid variable in the current environment;

  • hasattr(sam, "__getitem__") checks if variable sam could be indexed by sam[n];

  • 0 < len(sam) checks if sam have more than zero items;

  • then check sam[0] != "harry".

  • Warning: This should work when type(sam) == list. Other cases were not tested. If you are sure that sam is a list, then the code would not be too lengthy:

    print("hello", sam) if 0 < len(sam) and sam[0] != "harry" else None
    

Additional Contents

As other answers (for example, Johnsyweb stated, multiple statements on one line is not preferred (PEP 8 E701). So, for any possible Pythonic (PEP 8) solution, the one-line code may have to avoid explicit if, else and try, except.

As another comment by Thomash stated, a better solution for try, except should using a wrapping function. This adds another lines of code; however, calling the function can not only check sam but also other variables:

def check_harry(name):
    try:
        print("hello", name) if name[0] != "harry" else None
    except (NameError, TypeError, IndexError):
        pass

check_harry(uncle)
check_harry(sam)

This could be a more serious solution. Note that bare except is not recommended due to PEP 8 E722. Although this line of compulsive except: pass seems to be a waste of time (and I actually usually agree with that T_T), there lies some code style consideration.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ajz34
  • 113
  • 7
0

You are mixing a lot of things, which makes it hard to answer your question. The short answer is: As far as I know, what you want to do is just not possible in Python - for good reason!

The longer answer is that you should make yourself more comfortable with Python, if you want to develop in Python. Comprehensions are not hard to read. You might not be used to reading them, but you have to get used to it if you want to be a Python developer. If there is a language that fits your needs better, choose that one. If you choose Python, be prepared to solve problems in a pythonic way. Of course you are free to fight against Python, But it will not be fun! ;-)

And if you would tell us what your real problem is, you might even get a pythonic answer. "Getting something in one line" us usually not a programming problem.

AndyG
  • 39,700
  • 8
  • 109
  • 143
Achim
  • 15,415
  • 15
  • 80
  • 144
  • I love python! I was just demonstrating how i think comprehensions might be better structured but can't due to the colon which is the root of my problem/question ... I see by your answer that the multistatements seperated by colons such as try: if sam[0] != 'harry': print('hellp', sam) are not possible ... is this correct? thanks ... im just using this for some debug purposes so I'm looking for small simple code that can be removed easy and doesn't take up lots of space lol – Rhys May 29 '11 at 10:42
  • Yes, as far as I know it's not possible. But as somebody already statet: What you do is something different than comprehension. If you want to be able to remove the code easily, put it into a function. Regarding the "except: pass"-problem, think about an decorator which ignores exception or something like that. Again: Always try to describe your real problem, not the problem with the solution you have in mind already. ;-) – Achim May 29 '11 at 16:23
  • 3
    Why do people have to start their answer with uncalled for provocative statements like "you are mixing a lot of things"? Down vote if I can. – John Jiang Jan 09 '15 at 16:05
  • "Getting something in one line" us usually not a programming problem." —> but that is often a sysadmin problem, so the question is still relevant in this aspect. – Alex F Dec 20 '17 at 04:10
  • @JohnJiang Does not feel out of line. it's not a hostile-minded answer just a heads up type from someone trying to help. – WestCoastProjects Nov 10 '21 at 01:41
0

Based on ThomasH's answer:

for i in range(4): print "i equals 3" if i==3 else None

Output:

None
None
None
i equals 3

I propose to update as:

for i in range(4): print("i equals 3") if i==3 else print('', end='')

Output:

i equals 3

Note, I am in Python 3 and had to use two print commands. pass after else won't work.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jaydrill
  • 54
  • 8
0

This solution might be complex, but working my

one line of script can

`

$
$ test_var=$(python3 -c $"import yaml,sys; yaml_as_dict=(lambda :yaml.safe_load(open(f'{sys.argv[1]}','r').read()))()[sys.argv[2]][sys.argv[3]]; print(yaml_as_dict)" <argv1> <argv2> <argv3>)
$
$ echo $test_var
$ 

How to execute multiline python code from a bash script?

How can I write multi-line code in the Terminal use python?

How to define a bash variable from python EOF

P_M
  • 21
  • 2
-1
sam = ['harry', 'john']

print('hello ' + sam[0] if sam[0] != 'harry' else '')
qwerteee
  • 197
  • 9
-3

Here is an example:

for i in range(80, 90): print(i, end=" ") if (i!=89) else print(i)

Output:

80 81 82 83 84 85 86 87 88 89
>>>
ppwater
  • 2,315
  • 4
  • 15
  • 29
JZP
  • 1
  • 1