如何统一获取类和函数的字符串表示?

2 投票
4 回答
695 浏览
提问于 2025-04-16 04:20

我觉得用一个例子来解释这个问题最合适。假设我有一个方法,它可以计算两个向量之间的距离并打印出来。我还希望这个方法能打印出使用的距离测量方式。这个距离测量方式是通过调用这个方法的人传递进来的,形式是一个可以调用的对象。如果这个可调用对象是某个类的实例,我可以提供一个叫做 __str__ 的方法,这样它就能打印出距离测量的名称。但可调用对象也可以是一个函数,而我还没有找到在这种情况下修改 __str__ 的方法。以下是一些代码:

def distance(v1, v2, d):
    print d
    dist = d(v1, v2)
    print dist
    return dist

如果 d 是一个函数,执行 print d 会打印出类似 <function someFunc at 0x1b68830> 的内容。我该怎么改变这个呢?只打印出函数的名称就可以了,因为我通常会给它们起一些容易理解的名字。

4 个回答

1

你可以这样做:

import types
if isinstance(d, types.FunctionType):
    print "<function %s>" % d.__name__
2

我觉得函数是不能被继承的,这样的话你就无法改变一个函数的 __str__ 方法。其实让一个类像函数那样工作要简单得多,可以通过使用 __call__ 方法来实现。

函数有一个叫 func_name 的属性,它会返回函数的名字。

如果你决定使用 func_name 属性,那么你的可调用对象也需要有一个 func_name 属性。

既然你已经定义了类的 __str__ 方法,你可以把 func_name 设为一个属性,让它返回 str(self),可以这样做:

def dfunc(v1,v2):
    return 1

class FooDist(object):
    def __call__(self,v1,v2):
        return 1
    @property
    def func_name(self):
        return str(self)
    def __str__(self):
        return 'My FooDist'


def distance(v1, v2, d):
    print d.func_name
    dist = d(v1, v2)
    print dist
    return dist

distance(1,2,dfunc)
# dfunc
distance(1,2,FooDist())
# My FooDist
1

要获取一个函数的名字,可以参考这个问题。要获取一个类的名字,可以参考这个问题。把它们结合起来:

def distance(v1, v2, d):
    if hasattr(d, '__name__'):
        print d.__name__
    elif hasattr(d, '__class__'):
        print d.__class__.__name__
    else:
        print d   # unsure about this case
    dist = d(v1, v2)
    print dist
    return dist

撰写回答