检查一个类是否定义了函数的最快方法是什么?

204 投票
8 回答
165176 浏览
提问于 2025-04-16 13:29

我正在写一个人工智能状态空间搜索算法,创建了一个通用的类,可以快速实现搜索算法。子类会定义必要的操作,而算法会处理其他的事情。

我现在遇到问题了:我想避免一次又一次地重新生成父状态,所以我有一个函数,它可以返回对任何状态合法的操作:

def get_operations(self, include_parent=True):
    ops = self._get_operations()
    if not include_parent and self.path.parent_op:
        try:
            parent_inverse = self.invert_op(self.path.parent_op)
            ops.remove(parent_inverse)
        except NotImplementedError:
            pass
    return ops

而invert_op函数默认是会抛出异常的。

有没有比捕获异常更快的方法来检查这个函数是否未定义呢?

我在想可以检查一下是否在目录中存在,但这似乎不太对。hasattr是通过调用getattr来实现的,然后再检查是否抛出异常,这不是我想要的。

8 个回答

22

有没有比捕获异常更快的方法来检查一个函数是否未定义?

你为什么反对这样做呢?在大多数情况下,Python 编程中,宁可先尝试再说,也就是“先犯错再请求原谅”。;-)

hasattr 是通过调用 getattr 并检查是否抛出异常来实现的,这正是我不想要的。

那你为什么会这样想呢?下面的做法其实很符合 Python 的风格:

    try:
        invert_op = self.invert_op
    except AttributeError:
        pass
    else:
        parent_inverse = invert_op(self.path.parent_op)
        ops.remove(parent_inverse)

或者,

    # if you supply the optional `default` parameter, no exception is thrown
    invert_op = getattr(self, 'invert_op', None)  
    if invert_op is not None:
        parent_inverse = invert_op(self.path.parent_op)
        ops.remove(parent_inverse)

不过要注意,getattr(obj, attr, default) 基本上也是通过捕获异常来实现的。在 Python 的世界里,这没有什么问题!

77

这个在Python 2和Python 3中都能用

hasattr(connection, 'invert_opt') and callable(connection.invert_opt)

hasattr这个函数会返回True,如果连接对象里有一个叫invert_opt的属性。callable则是用来检查这个属性是否可以被调用(比如说,它是不是一个函数)。这里有一些文档链接,供你参考:

309

没错,可以用 getattr() 来获取一个属性,然后用 callable() 来检查它是不是一个方法:

invert_op = getattr(self, "invert_op", None)
if callable(invert_op):
    invert_op(self.path.parent_op)

需要注意的是,通常情况下,如果你用 getattr() 去获取一个不存在的属性,它会报错。不过,如果你给它指定一个默认值(在这里是 None),那么它就会返回这个默认值,而不会报错。

撰写回答