2

Currently I have something like the following

def writeThis(fileHandle, name):
 fileHandle.write('Hello ' + name)
writeThis(fh, 'Alice')

Something about this doesn't feel right however, it feels like I should try to minimize side effects and have something like the following

def foo(name):
 return 'Hello ' + name
fh.write(foo('Alice'))

Is the second option considered better practice? Does it matter?

asked Feb 14, 2019 at 16:54
1
  • Something needs to write the file. Maybe not the same function that performs the "logic", but probably a function. ... Right? Commented Feb 15, 2019 at 0:06

2 Answers 2

5

A function which returns a greeting as a string (your 2nd option) is a better practice. That way, the function has a single responsibility. Your code will be easier to maintain. In the future, you may need to change the file format (say you want to switch from XML to JSON). In the future, your customers may want to use the greeting same in more than one place (say, an e-mail or a GUI).

answered Feb 14, 2019 at 17:56
4

Returning a string has the disadvantage that you need to concatenate all the output into a string first, which can be inefficient if that string gets large. It might be better to write chunks separately, as soon as they are available.

In contrast, directly writing to a file has the disadvantage that the function is now coupled to a particular output medium (file-handle based output).

In practice, neither of these is a terribly huge issue. You should do whatever feels most natural in that particular case. In your hello-world level example, I'd just return the string.

Alternatives:

  • Let the function take a callback. The caller can then decide what callback to provide. For example:

    def writeThis(write, name):
     write('Hello ')
     write(name)
    # a caller that wants a string
    parts = []
    writeThis(parts.append, 'Alice')
    result = ''.join(parts)
    # a caller that wants to write to a file
    writeThis(fh.write, 'Alice')
    
  • Yield chunks of output as soon as available:

    def writeThis(name):
     yield 'Hello '
     yield name
    # a caller that wants a string
    result = ''.join(writeThis('Alice'))
    # a caller that wants to write to a file
    for chunk in writeThis('Alice'):
     fh.write(chunk)
    
  • Just use the file API and use a StringIO adapter if you want a string

    def writeThis(fh, name):
     fh.write('Hello ')
     fh.write(name)
    # a caller that wants a string
    from io import StringIO
    sio = StringIO()
    writeThis(sio, 'Alice')
    result = sio.getvalue()
    # a caller that wants to write to a real file
    writeThis(fh, 'Alice')
    
answered Feb 14, 2019 at 22:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.