Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 805
RandomGuy Avatar asked Dec 12 '22 17:12

RandomGuy


2 Answers

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
like image 146
Mark Tolonen Avatar answered Dec 30 '22 14:12

Mark Tolonen


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>
>>> 
like image 25
pyfunc Avatar answered Dec 30 '22 14:12

pyfunc