How do I add an additional print statement for every print statement called in my code? (preferably using code decorators)

Question:

I want to check if a print statement is being called and add an additional print statement after it, without having to add an empty print statement manually after every instance.
My output is currently like this:

Hello  
Hello  
Hello  
Hello

*(outputs this 10 times)*

while I would like it to look like this:

Hello

Hello

Hello

Hello

*(output 10 times as well in this pattern)*

I preferably want to use decorators as that is the easiest and best-looking solution, but another solution would also be okay!

I tried asking ChatGPT, but it doesn’t change anything about the output.

Currently, this is my code:

def readability(func):
  def wrapper(*args,**kwargs):
    result = func(*args, **kwargs)
    if callable(func) and func.__name__ == 'print':
      print(' ')
    return result
  return wrapper

@readability
def printing():
  j=10
  while j>0:
    print('hello')
    j-=1

printing()

Asked By: Acion

||

Answers:

Original answer:

original_print = print
def print(*args):
    original_print(*args)
    original_print('  ')

print('Hello')

Improved answer using __builtins__:

def print(*args):
    __builtins__.print(*args)
    __builtins__.print('  ')

Both version produce the following output:

Hello
<blank line>
Answered By: Friedrich

You could use contextlib.ContextDecorator to be able to use either a decorator or a context manager, which lets you control more finely where you want to use your modified print function.

In order to replace print, you just have to use print = your_own_function. You can still access the original print as __builtins__.print.

So, an example could be, with two sample personalized print functions which you can apply wherever you want: to a whole function using a decorator, or to a piece of code using a context manager:

from contextlib import ContextDecorator


def double_print(data):
    __builtins__.print(data)
    __builtins__.print()
    
def underlined_print(data):
    __builtins__.print(data)
    __builtins__.print('-'*len(str(data)))
    

class my_print_context(ContextDecorator):
    def __init__(self, print_function):
        self.print = print_function
    
    def __enter__(self):
        global print
        print = self.print
        return self

    def __exit__(self, *exc):
        global print
        print = __builtins__.print
        return False
    
    
def nums():
    for i in range(3):
        print(i)

We can use this like this:

@my_print_context(double_print)
def nums2():
    for i in range(3):
        print(i)
     
        
print('nNormal')        
nums()

print('nDecorated')
nums2()

print('nWith context manager')
with my_print_context(underlined_print):
    print('Hello')
    print('We are underlined')
    nums()

print('nAfter the context')
nums()

which outputs:

Normal
0
1
2

Decorated
0

1

2


With context manager
Hello
-----
We are underlined
-----------------
0
-
1
-
2
-

After the context
0
1
2
Answered By: Thierry Lathuille