Python函数对象的自定义打印语句

4 投票
5 回答
11558 浏览
提问于 2025-04-16 08:12

我知道如果我写一个类,我可以像下面这样定义一个自定义的打印函数。

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

但是,如果我想对一个函数对象做同样的事情呢?比如说,

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

我希望打印的内容不是像'<function f at 0x7f738d6da5f0>'这样的信息,而是能让我自己指定打印的内容。这样做的原因是,我打算把一堆函数对象存储在一个列表里,然后我想遍历这个列表,打印出人类能理解的函数类型描述,而不想增加额外的复杂性,比如说把函数对象和字符串放在元组里。

非常感谢你能提供的任何帮助。

编辑:我修改了我的例子,以更好地表达我想说的内容,不幸的是,我打错了,写成了'f()',其实我想写的是'f'。我感兴趣的是给函数对象自定义一个标签,而不是自定义返回值(这个显然是怎么做的)。对造成的任何困惑表示抱歉。

5 个回答

2

你不能改变打印一个函数时发生的事情,但你可以让一个类像函数一样工作:

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?
9

其他人建议使用文档字符串,但文档字符串应该更详细地描述函数的功能。如果你想要一个简短的属性来描述这个函数,下面的选项可能正是你需要的:

选项 1

你是说你想要改变一个函数对象的默认描述吗?

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

如果你想自定义上面列表中函数的描述,可以使用一个叫做装饰器。下面的装饰器会把每个被装饰的函数包装成一个对象,这个对象看起来像原来的函数,但有一个自定义的表示方式:

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)

输出

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

选项 2

另外,你可以在函数中存储属性,并根据需要显示这些属性:

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)

输出

a+b 11
a-b 5

选项 3

你也可以用装饰器来实现选项 2:

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)

输出

a+b 11
a-b 5
3

有几个错误:

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

在第一个例子中,当你调用 print 的时候,其实是在调用 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__

你应该使用文档字符串来说明你的意图。

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

你想做的事情是重写方法 __str__

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

撰写回答