如何检测Python3.x中未绑定方法的使用情况?

2024-04-20 11:21:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个库,它可以接受一个类函数或一个带有特定签名的普通函数。类通常如下所示:

class MyObject(object):
    def __init__(self, request):
       self.request = request

    def run(self):
        return 'OK'

函数格式如下:

^{pr2}$

它的用法是:

add_runner(MyObject, attr='run')
add_runner(my_func)

但有时人们会错误地使用这个类函数,并将类函数传递给我的库:

add_runner(MyObject.run)

我在Python2.x中检测到这是一个未绑定的方法,并引发一个错误来警告他们他们错误地使用了我的API,但在Python3.x中,我找不到任何方法来真正检测到他们做得不对。我错过了什么?在


Tags: 方法函数runselfaddreturnobjectinit
3条回答

在Python3中,无界方法与函数完全等价(参见Get defining class of unbound method object in Python 3中的讨论)

检查第一个参数name=='self'可能会有问题,因为方法的第一个参数不要求是'self'。可以使用任何有效的参数名(例如“我自己”、“这个”等)。在

我建议use继续使用参数检查,以确保调用方提供了一个具有您期望的调用签名的函数。在

在python3中,可以将unbound方法正确传递给add_runner:

class AnotherObject:
   def run(request):
     return "OK"

add_runner(AnotherObject.run)

如果您可以假设Py27及更高版本,那么下面的方法似乎可以工作:

def is_bound(method):
    return bool(getattr(method, '__self__', None))

在Py26中,除了im_self之外,还添加了__self__属性,以便与Py3兼容(有关详细信息,请参见documentation)。在

在Py2中,一个未绑定的方法将有一个__self__,但值将是None。绑定方法将有一个__self__,它对应于调用它的类的实例。在

在Py3中,“绑定”方法(在类的实例上调用的方法)将定义__self__。相反,“unbound”方法(类定义本身调用的方法)不会定义__self__。在

我认为这很好,我只是讨厌我必须检测self

def _is_unbound(fn):
    """
    This consistently verifies that the callable is bound to a
    class.
    """
    spec = inspect.getargspec(fn)
    has_self = len(spec.args) > 0 and spec.args[0] == 'self'
    is_bound = getattr(fn, im_self, None) is not None

    if not is_bound:
        if PY3 and inspect.isfunction(fn) and has_self:
            return True
        elif inspect.ismethod(fn):
            return True

    return False

相关问题 更多 >