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

我正在写一个AI状态空间searchalgorithm,我有一个通用的类,可以用来快速实现一个searchalgorithm。 一个子类将定义必要的操作,而algorithm则完成剩下的操作。

这里是我卡住的地方:我想要避免一次又一次地重新生成父状态,所以我有以下函数,它返回可以合法应用于任何状态的操作:

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函数默认会抛出。

有没有更快的方法来检查是否没有定义函数捕获exception?

我正在想办法检查目前的目录,但这似乎并不正确。 hasattr通过调用getattr并检查是否引发来实现,这不是我想要的。

是的,使用getattr()来获取属性,并使用callable()来validation它是一个方法:

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

请注意,当属性不存在时, getattr()通常会抛出exception。 但是,如果您指定一个默认值(在这种情况下为None ),则会返回该值。

它适用于Python 2和Python 3

 hasattr(connection, 'invert_opt') 

如果连接对象具有定义的函数invert_opthasattr返回True 。 这是您要放牧的文件

https://docs.python.org/2/library/functions.html#hasattr https://docs.python.org/3/library/functions.html#hasattr

有没有更快的方法来检查是否没有定义函数捕获exception?

你为什么反对? 在大多数Pythonic案件中,最好是要求宽恕而不是允许。 😉

hasattr通过调用getattr并检查是否引发来实现,这不是我想要的。

同样,为什么呢? 以下是Pythonic:

  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)基本上也是通过捕获exception来实现的。 在Python的土地上没有任何错误!

我喜欢Nathan Ostgard的回答,我投了赞成票。 但另一种解决问题的方法是使用memoizing装饰器,它将caching函数调用的结果。 所以,你可以继续,并有一个昂贵的function,计算出一些东西,但是当你打电话过来,后来的电话很快; 该函数的memoized版本在字典中查找参数,从实际函数计算结果时在dict中查找结果,并立即返回结果。

这是Raymond Hettinger的一个名为“lru_cache”的装饰器的配方。 这个版本现在在Python 3.2的functools模块中是标准的。

http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/

http://docs.python.org/release/3.2/library/functools.html

就像Python中的任何东西一样,如果你努力的努力,你可以在胆量上做一些非常讨厌的事情。 现在,这是讨厌的部分:

 def invert_op(self, op): raise NotImplementedError def is_invert_op_implemented(self): # Only works in CPython 2.x of course return self.invert_op.__code__.co_code == 't\x00\x00\x82\x01\x00d\x00\x00S' 

请帮我们一个忙,就是继续做你自己的问题,除非你是PyPy团队的黑客入侵Python解释器,否则不要使用它。 Pythonic有什么,我在这里是纯EVIL

这里的响应检查string是否是对象属性的名称。 需要额外的步骤(使用可调用的)来检查属性是否是一个方法。

所以它归结为:什么是最快的方式来检查对象obj是否有一个属性attrib。 答案是

 'attrib' in obj.__dict__ 

这是因为一个字典散列它的密钥,所以检查密钥的存在是很快的。

请参阅下面的时间比较。

 >>> class SomeClass(): ... pass ... >>> obj = SomeClass() >>> >>> getattr(obj, "invert_op", None) >>> >>> %timeit getattr(obj, "invert_op", None) 1000000 loops, best of 3: 723 ns per loop >>> %timeit hasattr(obj, "invert_op") The slowest run took 4.60 times longer than the fastest. This could mean that an intermediate result is being cached. 1000000 loops, best of 3: 674 ns per loop >>> %timeit "invert_op" in obj.__dict__ The slowest run took 12.19 times longer than the fastest. This could mean that an intermediate result is being cached. 10000000 loops, best of 3: 176 ns per loop