[python] 클래스에 함수가 정의되어 있는지 확인하는 가장 빠른 방법은 무엇입니까?

AI 상태 공간 검색 알고리즘을 작성 중이며 검색 알고리즘을 빠르게 구현하는 데 사용할 수있는 일반 클래스가 있습니다. 서브 클래스는 필요한 연산을 정의하고 알고리즘은 나머지를 수행합니다.

여기에 내가 붙어있는 곳이 있습니다 : 부모 상태를 반복해서 다시 생성하지 않기를 원하므로 다음 함수가 있습니다.이 함수는 모든 상태에 합법적으로 적용될 수있는 작업을 반환합니다.

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 함수는 기본적으로 throw됩니다.

예외를 잡는 것보다 함수가 정의되어 있지 않은지 확인하는 더 빠른 방법이 있습니까?

나는 dir에 존재하는 것을 확인하는 줄에 무언가를 생각하고 있었지만 그것이 옳지 않은 것 같습니다. hasattr은 getattr을 호출하고 그것이 발생하는지 확인하여 구현됩니다.



답변

예, getattr()속성을 가져 와서 callable()메소드인지 확인하는 데 사용하십시오.

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

getattr()속성이 존재하지 않는 경우 일반적으로 예외가 발생합니다. 그러나 기본값 ( None이 경우) 을 지정하면 대신 해당 값을 반환합니다.


답변

파이썬 2와 파이썬 3 모두에서 작동합니다.

hasattr(connection, 'invert_opt')

hasattrTrue연결 객체에 함수가 invert_opt정의 되어 있으면를 반환 합니다 . 여기 당신이 방목하는 문서가 있습니다

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


답변

예외를 잡는 것보다 함수가 정의되어 있지 않은지 확인하는 더 빠른 방법이 있습니까?

왜 그런 거에요? 대부분의 Pythonic 경우 허가보다 용서를 구하는 것이 좋습니다. 😉

hasattr은 getattr을 호출하고 그것이 발생하는지 확인하여 구현됩니다.

다시, 왜 그렇습니까? 다음은 꽤 파이썬입니다.

    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)기본적으로 예외를 포착하여 구현됩니다. 파이썬 땅에는 아무런 문제가 없습니다!


답변

여기의 응답은 문자열이 객체의 속성 이름인지 확인합니다. 속성이 메소드인지 확인하려면 추가 단계 (호출 가능 사용)가 필요합니다.

따라서 객체 obj에 속성 속성이 있는지 확인하는 가장 빠른 방법은 무엇입니까? 정답은

'attrib' in obj.__dict__

이것은 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


답변

나는 Nathan Ostgard의 답변이 마음에 들었고 투표했습니다. 그러나 문제를 해결할 수있는 또 다른 방법은 함수 데코레이터를 사용하여 함수 호출 결과를 캐시하는 것입니다. 따라서 무언가를 알아낼 수있는 고가의 기능을 사용할 수 있지만, 계속해서 호출하면 후속 호출이 빠릅니다. 메모 된 버전의 함수는 dict에서 인수를 찾고 실제 함수가 결과를 계산할 때 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


답변

파이썬의 어떤 것과 마찬가지로, 열심히 노력하면 용기를 얻고 정말 불쾌한 것을 할 수 있습니다. 이제 불쾌한 부분이 있습니다.

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 인터프리터를 해킹하지 않는 한 우리에게 호의를 베푸십시오. 귀하의 질문에 대해 계속하고 PyPy 팀에 속하지 않는 한 이것을 사용 하지 마십시오 . 당신이 가진 것은 Pythonic이고, 내가 가진 것은 순수한 EVIL 입니다.


답변

수업을 진행할 수도 있습니다.

import inspect


def get_methods(cls_):
    methods = inspect.getmembers(cls_, inspect.isfunction)
    return dict(methods)

# Example
class A(object):
    pass

class B(object):
    def foo():
        print('B')


# If you only have an object, you can use `cls_ = obj.__class__`
if 'foo' in get_methods(A):
    print('A has foo')

if 'foo' in get_methods(B):
    print('B has foo')