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()
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>
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
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()
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>
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