Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
OneLiner question
#1
Greetings!
I'm trying to shorten my code and I'd like to use OneLiners.
I Googled it and it is not that clear how to use it.
Here is the code I'm trying to write in a one-liner and it is not working.
w = open('c:/01/oneLiner.txt','w') 
with open('c:/01/mytext-2.txt','r') as f :
    for i in f :
        i=i.strip()
        if "PG" in i :
            print(i)
            w.write(f"{i}\n")
w.close()
OneLiner
w = open('c:/01/oneLiner.txt','w') 
with open('c:/01/mytext-2.txt','r') as f :
    w.write(f"{i}\n") i=i.strip() for i in f if "PG" in i   
w.close()
Here is the error:
     w.write(f"{i}\n") i=i.strip() for i in f if "PG" in i
                      ^
SyntaxError: invalid syntax
All help is appreciated!
Thank you!
Reply
#2
It makes me feel slimy posting this:
with open('input.txt', 'r') as fin:
    with open('output.txt', 'w') as fout:
        [fout.write(f'{x.strip()}') for x in fin if 'TEST' in x]
That is so wrong. HORRIBLE programming. A comprehension is used to make an iterable. It should not be used just for the side effects.
Reply
#3
Use this for example
with open('f.txt') as f, open('w.txt', 'w') as w:
    w.writelines((i.strip() + '\n' for i in f if 'PG' in i))
Proof
import io
w = io.StringIO()
f = io.StringIO("""\
spam spam PG spam
eggs eggs eggs
ham PG ham ham
cheese cheese
""")

w.writelines((i.strip() + '\n' for i in f if 'PG' in i))

print(repr(w.getvalue()))
Output:
'spam spam PG spam\nham PG ham ham\n'
If you write the one-line body of the with statement on the same line as the with statement, it is truly a one-liner.

An alternative is to use pathlib
from pathlib import Path

Path('w.txt').write_text("".join(i.strip() + '\n' for i in Path('f.txt').read_text().splitlines() if 'PG' in i))
but you need to import Path first.
tester_V likes this post
Reply
#4
(Feb-14-2023, 03:02 AM)deanhystad Wrote: It makes me feel slimy posting this:
with open('input.txt', 'r') as fin:
    with open('output.txt', 'w') as fout:
        [fout.write(f'{x.strip()}') for x in fin if 'TEST' in x]
That is so wrong. HORRIBLE programming. A comprehension is used to make an iterable. It should not be used just for the side effects.

What do you mean by " this is wrong"? Could you tell what is "right"?
I would really appreciate it if you elaborate on this, so I (and others) would not do "HORRIBLE programming".

Thank you!
Reply
#5
Alternative way is to use print:

with open('r.txt') as r, open('w.txt', 'w') as w:
    print(*(row.strip() for row in r if 'PG' in row), file=w, sep='\n')
Gribouillis and tester_V like this post
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#6
(Feb-14-2023, 06:07 AM)tester_V Wrote: What do you mean by " this is wrong"? Could you tell what is "right"?
Because it is example of using list comprehension for side-effects - just to make one-liner instead of regular loop, i.e. you are not interested of resulting list/generator expression, which by the way will be bunch of Nones

Compare it with @Gribouillis example
(Feb-14-2023, 06:02 AM)Gribouillis Wrote:
with open('f.txt') as f, open('w.txt', 'w') as w:
    w.writelines((i.strip() + '\n' for i in f if 'PG' in i))
Here you create a generator expression which is passed as argument to writelines()
Although I would use f-string

with open('f.txt') as f, open('w.txt', 'w') as w:
    w.writelines((f'{i.strip()}\n' for i in f if 'PG' in i))
Also note that using strip() makes sense only if you have white spaces that you want to remove before adding back new-line
tester_V likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
(Feb-14-2023, 06:07 AM)tester_V Wrote: What do you mean by " this is wrong"? Could you tell what is "right"?

This is wrong:
[print(x / 10) for x in range(10)]
It returns 10 times None and 10 times a side effect print is used.
Right is not to use a comprehension with side effects.

values = [x / 10 for x in range(10)]
for value in values:
    print(value)
This is also true for functions. This is a function with a side effect (printing).

def foo(x):
    print("Calculating")
    return x / 10
This function does two things. The expected behavior, to return some object and the side effect which is caused by the print function.
tester_V likes this post
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#8
Thank you for coaching!
That is why people come back to this site.
It is not just a place to get help but more... Help to understand the code... become better coder,

Thank you, guys!
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020