Q:

How to print the args and evaluate them?

I'd like to overload the print function so that whenever I call it, I print the args, and the literal args. For example:
>>> print(2 + 2.0)
2 + 2.0 : 4.0

>>> print(2 > 2.0)
2 > 2.0 : False

I suppose it might be simpler and more sensible to instead create a new function, say func_print. I'm not sure, so I'll take both approaches and any attached reasoning.
I've been trying to learn decorators as I feel they're the best approach, but am having difficulty understanding the structure.

A:

The desired behaviour you are mentioning (getting the expression before Python evaluates it) isn't possible (or easily possible, without digging into very deep of Python internals).
When python sees 2 + 2.0, it will evaluate it first and your function gets the result, 4.0. Your function will not know, how the python got the result in first place.
One way to get around this is putting the expression in string and evaluate it lazily with for example eval():
def func_print(expression):
    print("{} : {}".format(expression, eval(expression)))

func_print('2 + 2.0')

This prints:
2 + 2.0 : 4.0

Overloading builtin functions isn't good idea, because other functions in your code might depend on the old behaviour. 
But if you insist, print() in Python3 is just classic function, so you can freely do this:
import sys

def func_print(expression, *args, **kwargs):
    sys.stdout.write("{} : {}\n".format(expression, eval(expression)))

old_print_function = print

print = func_print
print('2 + 2.0')

print = old_print_function

The result is:
2 + 2.0 : 4.0

