所有的callables都有__name__吗?

ale*_*dro 10 python

我有一个装饰器,记录装饰功能的名称(以及其他内容).

访问__name__装饰函数的属性是否安全?或者是否有一些可调用的类型没有我尚未遇到的名称?

ale*_*dro 9

用其他答案和评论的摘要回答我自己的问题.

并非所有的callables都有__name__.

  • 定义的类的实例__call__可能没有__name__属性.

  • 使用创建的对象functools.partial没有__name__属性.

解决方法是使用三个参数getattr:

name = getattr(callable, '__name__', 'Unknown')
Run Code Online (Sandbox Code Playgroud)

或者使用repr(callable)而不是'Unknown',其中包括有关可调用的更多信息:

name = getattr(callable, '__name__', repr(callable))
Run Code Online (Sandbox Code Playgroud)


sob*_*evn 7

功能非常安全:

def d():
    pass

l = lambda: None
print(d.__name__)
print(l.__name__)
Run Code Online (Sandbox Code Playgroud)

输出:

> d 
> <lambda>
Run Code Online (Sandbox Code Playgroud)

您甚至可以安全地修改它(例如用于debuging目的):

l.__name__ = 'Empty function'
print(l.__name__)  # Empty function
Run Code Online (Sandbox Code Playgroud)

但要注意带__call__方法的类,它们没有__name__属性.

class C(object):
    def __call__(self):
        print('call')

print(C().__name__)  # AttributeError: 'C' object has no attribute '__name__'
Run Code Online (Sandbox Code Playgroud)

更新

正如@felipsmartins在评论中指出的那样,functools.partial也没有__name__属性.

有关:

什么是Python中的"可调用"?

  • 当然,你可以通过使用三个arg`getattr`来忽略这个问题:`getattr(callable,'_ name__','Unknown')`将避免异常并给你一些输出.或者,`getattr(callable,'_ command__',repr(callable))`为你提供一个更加量身定制的`repr`版本(这应该有助于实现其类实现`__call__`的实例. (2认同)