15

Consider:

def generator():
    nums = ['09', '98', '87', '76', '65', '54', '43']
    s_chars = ['*', '&', '^', '%', '$', '#', '@',]
  
    data = open("list.txt", "w")
    for c in s_chars:
        for n in nums:
            data.write(c + n)
    data.close()

I would like to add a newline after every "c + n".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
b1ackzer0
  • 165
  • 1
  • 1
  • 5
  • 3
    Can you please add a sample how you want the output to look? It's not exactly clear where you want to add the newlines. – Jan Hudec Mar 25 '11 at 06:05

9 Answers9

19

Change

data.write(c + n)

to

data.write("%s%s\n" % (c, n))
dietbuddha
  • 8,556
  • 1
  • 30
  • 34
  • 1
    This is complicated, compared to a simple `print`, which is designed to do just what the original poster asked. – Eric O. Lebigot Mar 25 '11 at 14:55
  • @Ignacio: I would indeed not say that `data.write('\n')` is "wrong". However, I do think that it goes against the Zen of Python ("There should be one-- and preferably only one --obvious way to do it."): since `print` is designed to add a newline, it feels really strange to me not to use it in this case. – Eric O. Lebigot Mar 25 '11 at 16:50
  • 2
    @EOL: I disagree that `print` is the "obvious" way here. In order to use `print` with a file handle under Python 2.x, you have to know the redirect operator `>>` which never gets used in any other place in the language. The print-chevron is just syntactic sugar for `write()` anyways. `file.write()` is designed for getting your (simple) data into a file, irrespective of those data's contents. In Python 3, I could perhaps agree with you. – jscs Mar 26 '11 at 01:15
  • @Josh: Fair enough. :) On the other hand, the chevron operator in Python 2.x is a must when you have lots of newline-separated lines to print to a file: doing `print >> …, …` is much lighter than doing a lot of `….write("%s\n" % …)`. It is also arguably more legible, as it means "I'm printing lines with newlines", whereas the format string in `write()` has to be visually parsed before coming to this conclusion. – Eric O. Lebigot Mar 26 '11 at 10:41
  • 1
    Don't know what you mean by "lighter". I do see and cede your point about legibility, however; that's a good way to look at it. – jscs Mar 27 '11 at 17:32
  • @Josh: Thanks. :) Instead of "lighter", I should have said "is shorter and easier to type". – Eric O. Lebigot Apr 05 '11 at 09:33
6

A properly-placed data.write('\n') will handle that. Just indent it appropriately for the loop you want to punctuate.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
4

As other answers gave already pointed out, you can do it by appending a '\n' to c+n or by using the format string "%s%s\n".

Just as a matter of interest, I think it would be more Pythonic to use a list comprehension instead of two nested loops:

data.write("\n".join("%s%s"%(c, n) for c in s_chars for n in nums))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MAK
  • 26,140
  • 11
  • 55
  • 86
  • Won't this construct the entire string in memory before writing it out? – detly Mar 25 '11 at 06:32
  • @detly: Yes it does. In this case the string generated should be short enough. It should be somewhat faster as long as there is enough memory. – MAK Mar 25 '11 at 06:34
  • 3
    @detly: I added [an answer with the same basic behavior that avoids that peak memory usage issue](http://stackoverflow.com/a/34440329/364696) precisely to solve that. Too few people know about `writelines`. My answer uses additional builtins to push all the work to C, but this answer could still get the benefit of peak memory usage reduction with the small tweak: `data.writelines('%s%s\n' % (c, n) for c in s_chars for n in nums)` – ShadowRanger Dec 23 '15 at 16:58
1

Change

data.write(c + n)

to

data.write(c + n + '\n')
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marc Poulin
  • 81
  • 2
  • 2
1

Pushing more work to the C layer with writelines and product:

from future_builtins import map  # Only do this on Python 2; makes map generator function
import itertools

def generator():
    nums = ['09', '98', '87', '76', '65', '54', '43']
    s_chars = ['*', '&', '^', '%', '$', '#', '@',]
    # Append newlines up front, to avoid doing the work len(nums) * len(s_chars) times
    # product will realize list from generator internally and discard values when done
    nums_newlined = (n + "\n" for s in nums)

    with open("list.txt", "w") as data:
        data.writelines(map(''.join, itertools.product(s_chars, nums_newlined)))

This produces the same effect as the nested loop, but does so with builtins implemented in C (in the CPython reference interpreter anyway), removing byte code execution overhead from the picture; this can dramatically improve performance, particularly for larger inputs, and unlike other solutions involving '\n'.join of the whole output into a single string to perform a single write call, it's iterating as it writes, so peak memory usage remains fixed instead of requiring you to realize the entire output in memory all at once in a single string.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

Python's print is the standard "print with newline" function.

Therefore, you can directly do, if you use Python 2.x:

print  >> data, c+n

If you use Python 3.x:

print(c+n, file=data)
Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
0

This one works for me

with open(fname,'wb') as f:
    for row in var:
        f.write(repr(row)+'\n')
DACW
  • 2,601
  • 2
  • 18
  • 16
  • An explanation would be in order. E.g., why is it simpler than the previous answers? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/25937161/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). Can you – Peter Mortensen Jul 04 '22 at 15:35
-1

Use

def generator():
     nums = ['09', '98', '87', '76', '65', '54', '43']
     s_chars = ['*', '&', '^', '%', '$', '#', '@',]

     data = open("list.txt", "w")
     for c in s_chars:
        for n in nums:
           data.write(c + n + "\n")
     data.close()

or

def generator():
     nums = ['09', '98', '87', '76', '65', '54', '43']
     s_chars = ['*', '&', '^', '%', '$', '#', '@',]

     data = open("list.txt", "w")
     for c in s_chars:
        for n in nums:
           data.write(c + n)
        data.write("\n")
     data.close()

depending on what you want.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
euphoria83
  • 14,768
  • 17
  • 63
  • 73
-1

I think you can use join to simplify the inner loop:

data = open("list.txt", "w")
for c in s_chars:
    data.write("%s%s\n" % (c, c.join(nums)))
data.close()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hzm
  • 420
  • 4
  • 9