开发者

How to get string representations of classes and functions uniformly?

I think is is best explained with an example. Suppose I have a method that calculates the distances between two vectors and prints it. I also want that method to print the distance measure that was used. The distance measure is given to the function by the caller in the form of a callable object. If the callable is an instance of some class, I can provide the __str__ method to make it print out the name of the distance measure. But the callable can also be a function, and I have not found a way to change __str__ in that case. Some code:

def distance(v1, v2, 开发者_StackOverflow社区d):
    print d
    dist = d(v1, v2)
    print dist
    return dist

If d is a function, print d will print out something like <function someFunc at 0x1b68830>. How can I change this? Just printing out the name of the function would be fine, since I usually give them readable names.


I don't think functions can be subclassed, which is what you'd need to do in order to change a function's __str__ method. It's much easier to make a class behave like functions (using the __call__ method).

Functions have a func_name attribute, that returns the function's name.

If you choose to use the func_name attribute, then your callable objects would need a func_name attribute too.

Since you've already defined the class's __str__ method, you could make func_name a property to return str(self) like this:

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


To get a function's name, see this question. To get a class's name, see this question. Putting them together:

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


You can do

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


You can uniformly give both classes and functions your own attributes:

class MyDistanceMeasure:
    name = "mine"
    #...

def another_distance_measure(x,y):
    #...

another_distance_measure.name = "another"

then:

def distance(v1, v2, d):
    print d.name
    # or..
    print getattr(d, 'name', "unknown")

    dist = d(v1, v2)
    print dist
    return dist
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜