Home > Back-end >  How to write for loop with condition in one line
How to write for loop with condition in one line

Time:04-15

Here is the original code:

import site; 
import re 

for i in site.getsitepackages():
    package = re.search("^/usr/local/lib/.*/dist-packages$", i)
    if package is None:
        continue
    print(package.string)

Output:

/usr/local/lib/python3.8/dist-packages

Here is the one line code:

import site; import re; for i in site.getsitepackages(): package = re.search("^/usr/local/lib/.*/dist-packages$", i); if package is None: continue; print(package.string)

Output:

  File "/tmp/ipykernel_2984/3719293883.py", line 1
    import site; import re; for i in site.getsitepackages(): package = re.search("^/usr/local/lib/.*/dist-packages$", i); if package is None: continue; print(package.string)
                            ^
SyntaxError: invalid syntax

I want to convert the above multiple lines into one line, and then run it in the bash command line:

python3 -c "<one line python code>"

CodePudding user response:

Why a single line? It will impact readability.

Just use a heredoc:

python3 <<!
import site;
import re

for i in site.getsitepackages():
     package = re.search("^/usr/local/lib/.*/dist-packages$", i)
     if package is None:
         continue
     print(package.string)
!

CodePudding user response:

While it is possible to join some python lines together with a semicolon, you can not do that with loops. See this answer

Because the Python grammar disallows it. See the documentation:

stmt_list ::= simple_stmt (";" simple_stmt)* [";"]

Semicolons can only be used to separate simple statements (not >compound statements like for). And, really, there's almost no >reason to ever use them even for that. Just use separate lines. >ython isn't designed to make it convenient to jam lots of code >onto one line.

However, to run a loop with python -c you can just run it over multiple lines. For example, the command below prints out the numbers 0 - 9 on seperate lines:

python -c 'while i in range(10):
    print(i)
'

CodePudding user response:

The issue is with the for command, which is not allowed to be used with the ; operator or with more than one : operator in Python.

There are a few ways you could massage this sort of thing into working, but the simplest is with a clever use of list comprehensions.

import re, site; [print(package.string) for i in site.getsitepackages() if (package := re.search("^/usr/local/lib/.*/dist-packages$", i))]

Which you can execute from bash like:

pyhton3 -c 'import re, site; [print(package.string) for i in site.getsitepackages() if (package := re.search("^/usr/local/lib/.*/dist-packages$", i))]'

The above takes advantage of the fact that print(package.string) only gets executed when the if is true. It also takes advantage of the := "walrus" in-place assignment operator, which works like the normal = except that you can use it inside a formula or list comprehension.

You can also use a here doc, if this is in a fully-fledged bash script.

python3 <<!
import re
import site
for i in site.getsitepackages():
    if package := re.search("^/usr/local/lib/.*/dist-packages$", i):
        print(package.string)
!

And finally you can use in-line newlines from bash:

python -c $'import re, site\nfor i in site.getsitepackages():\n if package := re.search("^/usr/local/lib/.*/dist-packages$", i):\n  print(package.string)'

When you place a $ in front of a single-quoted string, then bash will expand backslash escaped newlines and other backslash escapes. (Be careful when combining this with regex though!)

  • Related