RandomGuy
RandomGuy

Reputation: 1678

custom print statement for python function objects

I know that if I write a class, I can definite a custom print function as below.

>>> class F:
...     def __str__(self):
...             return 'This describes the data of F.'
... 
>>> f = F()
>>> print f
This describes the data of F.

But, what if I want to do the same for a function object? For example,

>>> def f():
...     pass
... 
>>> g = f
>>> print g
<function f at 0x7f738d6da5f0>

Instead of '<function f at 0x7f738d6da5f0>', I'd like to somehow specify what was printed. The motivation for doing this is that I'm going to store a bunch of function objects in a list, and I'd like to iterate over the list and print human-readable descriptions of the types of functions without adding additional complexity, e.g., tuples of function objects and strings.

Thanks in advance for any help you can provide.

Edit: I changed my example to reflect what I was trying to convey, unfortunately I typed 'f()' when I meant 'f'. I am interested in a custom label for the function object, not customizing the return (which it is obvious how to do). Sorry for any confusion this has caused.

Upvotes: 4

Views: 12426

Answers (5)

Mark Tolonen
Mark Tolonen

Reputation: 178429

Others have suggested doc strings, but a doc string should probably be more descriptive of what the function does. If you want a short attribute describing the function, one of the options below may be what you are looking for:

Option 1

Are you saying you want to change the default description of a function object?

>>> def f1(): pass
...
>>> def f2(): pass
...
>>> L = [f1,f2]
>>> print L
[<function f1 at 0x00AA72F0>, <function f2 at 0x00AA73B0>]

If you want to customize the description of the functions in the list above, use a decorator. The decorator below wraps each function decorated into an object that acts like the original function, but has a custom representation:

def doc(s):
    class __doc(object):
        def __init__(self,f):
            self.func = f
            self.desc = s
        def __call__(self,*args,**kwargs):
            return self.func(*args,**kwargs)
        def __repr__(self):
            return '<function {0} "{1}">'.format(self.func.func_name,self.desc)
    return __doc

@doc('a+b')
def sum(a,b):
    return a + b

@doc('a-b')
def diff(a,b):
    return a - b

L = [sum,diff]
print L
for f in L:
    print f(5,3)

Output

[<function sum "a+b">, <function diff "a-b">]
8
2

Option 2

Alternatively, you can store attributes in your functions and display them as needed:

def sum(a,b):
    return a + b
sum.desc = 'a+b'

def diff(a,b):
    return a-b
diff.desc = 'a-b'

L = [sum,diff]
for f in L:
    print f.desc,f(8,3)

Output

a+b 11
a-b 5

Option 3

You can do option 2 with a decorator also:

def doc(s):
    def __doc(f):
        f.desc = s
        return f
    return __doc

@doc('a+b')
def sum2(a,b):
    return a + b

@doc('a-b')
def diff2(a,b):
    return a - b

L = [sum2,diff2]
for f in L:
    print f.desc,f(8,3)

Output

a+b 11
a-b 5

Upvotes: 9

Jochen Ritzel
Jochen Ritzel

Reputation: 107786

You cant change what happens when you print a function, but you can make a class behave like a function:

class f(object):
    def __str__(self):
        return "I'm a function!"

    def __call__(self):
        print "who called?"


print f # I'm a function!
f() # who called?

Upvotes: 2

Karl Knechtel
Karl Knechtel

Reputation: 61654

>>> g = f # no ()! That *calls* the function.
>>> print g
<function f at 0x########>

Upvotes: 0

pyfunc
pyfunc

Reputation: 66739

Few errors:

>>> def f():
...     pass
... 
>>> g = f()     <---- g is the return value of running f
>>> print g
None

in the first case, when you call print, you are calling a string representation of f

>>> f = F()
>>> print f    <----- f is an instance of class F and 
               <----- print f tries to provide a suitable string representation
               <----- by calling f.__str__

You should use doc strings for your motives

>>> def f():
...     " some doc"
...     pass
... 
>>> 
>>> f.__doc__
' some doc'
>>> 

What you are trying to do is override the method wrapper __str__.

>>> def f():
...     "some documentation .."
...     pass
... 
>>> 
>>> f.__str__
<method-wrapper '__str__' of function object at 0x100430140>
>>> 

Upvotes: 3

Utku Zihnioglu
Utku Zihnioglu

Reputation: 4883

Functions return values. The value assigned to g variable is going to be printed. If you want to print something, just make sure the function f, returns a string.

>>> def f():
...     return "Print me"
... 
>>> g = f()
>>> print g
Print me

Upvotes: 0

Related Questions