【问题标题】:When does Callable lack __module__?Callable什么时候缺少__module__?
【发布时间】:2019-09-27 11:00:51
【问题描述】:

我正在为 python 中的函数制作日志装饰器:

import logging
from typing import Callable
from functools import wraps


def function_logging(fn: Callable) -> Callable:
    fn_logger = logging.getLogger(fn.__module__ + '.' + fn.__name__)

    @wraps(fn)
    def wrapper(*args, **kwargs):
        fn_logger.info("Args: {}".format(args))
        fn_logger.info("Kwargs: {}".format(kwargs))
        result = fn(*args, **kwargs)
        fn_logger.info("Return: {}".format(result))
        return result

    return wrapper

PyCharm 的静态分析告诉我,我不能指望Callable 具有__module__ 属性。到目前为止,我还没有遇到过失败的情况。有谁知道在什么情况下可能会遇到没有__module__ 属性的Callable

【问题讨论】:

  • 据我所知,通常唯一没有 __module__ 属性的东西是内置类型的实例。但是,这些都不是可调用的。我不确定元类是否可以防止在类、其实例或方法上添加__module__(即使可以,我也不确定它是否安全)。我能够找到一种边缘案例。内置类型的方法描述符,如range.count(可调用)没有__module__。在实例上,例如range(0).count __module__None,除了特殊方法,例如range(0).__str__ 不存在的地方。
  • @jdehesa 很可能就是这样。跟进:除了Callable,还有其他类型适合排除这些边缘情况吗?
  • 我不确定有什么比Callable 更精确。我什至不确定这些案例是否应该表现得像那样,这就是 PyCharm 抱怨的原因,或者对于“什么东西应该或不应该有__module__”这个问题没有确切的答案。在任何情况下,您都可以随时执行(getattr(fn, '__module__', None) or '(none)') 之类的操作。
  • 我会注意到mypy对此没有任何问题。
  • @modesitt mypy 通常比 PyCharm 在后台使用的任何东西都表现得更好。

标签: python pycharm typing structural-typing


【解决方案1】:

这是一个例子:

list.__add__

这是一个没有__module__ 的可调用对象。它是列表连接的未绑定方法。

一般来说,callables 没有__module__ 的要求。只需要可以调用它们即可。也没有要求可调用对象具有 __name__,并且对于大多数可调用类型,将 functools.wraps 与它们一起使用是没有意义的。

你的装饰器需要一个普通 Python 函数类型的实例;它不能接受任意可调用对象。如果你要给它类型提示,你应该用那个类型来提示它:

def function_logging(fn: types.FunctionType) -> types.FunctionType:
    ...

【讨论】:

    猜你喜欢
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2011-09-28
    • 1970-01-01
    • 2012-08-07
    • 2012-04-05
    相关资源
    最近更新 更多