你如何为函数实现__str__? [英] How do you implement __str__ for a function?

查看:91
本文介绍了你如何为函数实现__str__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个函数 foo

  def foo(x) :
pass

通过调用 str repr 会给你带来一些无聊的感觉:

  str(foo)
'< function foo at 0x119e0c8c8>'

我想知道是否可以重写一个函数的 __ str __ 方法来打印其他内容。基本上,我想这样做:

  str(foo)
我是foo!'

现在,我明白函数的描述应该来自 __ doc __ 这是函数的文档字符串,但这仅仅是一个实验。

为了解决这个问题,我遇到了实现 __ str __ for classes 如何为类定义__str__方法?



这种方法涉及使用 __ str __ 方法定义元类,然后尝试在实际的类中分配 __元类__ 钩子。



我想知道是否可以对类 function 做同样的事情,所以这是我尝试的 -

  In [355]:foo .__ class__ 
Out [355]:function

In [356 ]:f类ancyfunction(type):
...:def __str __(self):
...:return self .__ name__
...:

在[357 ]:foo .__ class __.__ metaclass__ = fancyfunction
------------------------------------- --------------------------------------
TypeError Traceback(最近的最后一次调用)

我认为这不起作用,但值得一试!



因此,为函数实现 __ str __ 的最佳方式是什么?

解决方案

Python中的函数只是一个可调用的对象。使用 def 来定义函数是创建这样一个对象的一种方法。但实际上并没有什么能阻止你创建一个可调用类型并创建一个实例来获得一个函数。



所以下面两件事情基本相同:

  def foo():
print('hello world')


class FooFunction:
def __call__(self):
print('hello world')

foo = FooFunction()

除了最后一个明显允许我们设置函数类型的特殊方法,如 __ str __ 和<$ c
$ b $ pre code> class FooFunction:
def __call__(self):$; $ c $ _ $ rep $ __ 。

b $ b print('hello world')

def __str__(self):
return'Foo function'
$ b $ f foo = FooFunction()
print(foo)#foo函数

但是为此创建一个类型变得有点乏味,它也是使它更难以理解该功能的作用:毕竟, def 语法允许我们 定义函数体。所以我们希望保持这种状态!



幸运的是,Python有这个很棒的功能,我们可以在这里使用这个功能。我们可以创建一个函数装饰器,该函数装饰器将自定义类型中的任何函数包装起来,该类型为 __ str __ 调用一个自定义函数。这可能看起来像这样:

  def with_str(str_func):
def wrapper(f):
类FuncType:
def __call__(self,* args,** kwargs):
#调用原始函数
返回f(* args,** kwargs)
def __str__( self):
#调用自定义的__str__函数
返回str_func()

#使用functool.wraps进行装饰,使得函数的结果如f
返回functools。 (f)(FuncType())
返回包装

然后我们可以用它来只需简单地装饰一个 __ str __ 函数即可。看起来像这样:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $'$'$ $ $ $''这是foo函数的__str__'

@with_str(foo_str)
def foo():
print('hello world')





 >>> str(foo)
'这是foo函数'
>>>的__str__。 foo()
hello world

显然,这样做有一些限制和缺点,因为你不能 重现了 def> 会为装饰器中的新函数执行的操作。



例如,使用 inspect 模块查看参数将无法正常工作:对于可调用类型,它将包含 self 参数,并且在使用通用装饰器时,它只能报告 wrapper 的细节。但是,可能存在一些 解决方案,例如在,这将允许你恢复一些的功能。



但是,这通常意味着您只需投入大量精力就可以很少使用函数对象来处理 __ str __ 工作。所以你应该考虑你的函数是否真的需要一个 __ str __ 实现,然后你将在那些函数上做什么样的操作。


Given a function foo:

def foo(x):
     pass

Printing its representation by invoking str or repr gives you something boring like this:

str(foo)
'<function foo at 0x119e0c8c8>'

I'd like to know if it is possible to override a function's __str__ method to print something else. Essentially, I'd like to do:

str(foo)
"I'm foo!'

Now, I understand that the description of a function should come from __doc__ which is the function's docstring. However, this is merely an experiment.

In attempting to figure out a solution to this problem, I came across implementing __str__ for classes: How to define a __str__ method for a class?

This approach involved defining a metaclass with an __str__ method, and then attempting to assign the __metaclass__ hook in the actual class.

I wondered whether the same could be done to the class function, so here's what I tried -

In [355]: foo.__class__
Out[355]: function

In [356]: class fancyfunction(type):
     ...:     def __str__(self):
     ...:         return self.__name__
     ...:     

In [357]: foo.__class__.__metaclass__ = fancyfunction
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

I figured it wouldn't work, but it was worth a shot!

So, what's the best way to implement __str__ for a function?

解决方案

A function in Python is just a callable object. Using def to define function is one way to create such an object. But there is actually nothing stopping you from creating a callable type and creating an instance of it to get a function.

So the following two things are basically equal:

def foo ():
    print('hello world')


class FooFunction:
    def __call__ (self):
        print('hello world')

foo = FooFunction()

Except that the last one obviously allows us to set the function type’s special methods, like __str__ and __repr__.

class FooFunction:
    def __call__ (self):
        print('hello world')

    def __str__ (self):
        return 'Foo function'

foo = FooFunction()
print(foo) # Foo function

But creating a type just for this becomes a bit tedious and it also makes it more difficult to understand what the function does: After all, the def syntax allows us to just define the function body. So we want to keep it that way!

Luckily, Python has this great feature called decorators which we can use here. We can create a function decorator that will wrap any function inside a custom type which calls a custom function for the __str__. That could look like this:

def with_str (str_func):
    def wrapper (f):
        class FuncType:
            def __call__ (self, *args, **kwargs):
                # call the original function
                return f(*args, **kwargs)
            def __str__ (self):
                # call the custom __str__ function
                return str_func()

        # decorate with functool.wraps to make the resulting function appear like f
        return functools.wraps(f)(FuncType())
    return wrapper

We can then use that to add a __str__ function to any function by simply decorating it. That would look like this:

def foo_str ():
    return 'This is the __str__ for the foo function'

@with_str(foo_str)
def foo ():
    print('hello world')

>>> str(foo)
'This is the __str__ for the foo function'
>>> foo()
hello world

Obviously, doing this has some limitations and drawbacks since you cannot exactly reproduce what def would do for a new function inside that decorator.

For example, using the inspect module to look at the arguments will not work properly: For the callable type, it will include the self argument and when using the generic decorator, it will only be able to report the details of wrapper. However, there might be some solutions, for example discussed in this question, that will allow you to restore some of the functionality.

But that usually means you are investing a lot of effort just to get a __str__ work on a function object which will probably very rarely be used. So you should think about whether you actually need a __str__ implementation for your functions, and what kind of operations you will do on those functions then.

这篇关于你如何为函数实现__str__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆