2010-02-04 8 views

답변

16

저는 프레임 객체 레벨에서 호출 된 실제 파이썬 함수 객체를 찾는 방법이 없다고 생각합니다. 코드가 공통의 규칙에 의존하는 경우

그러나 : 방법 self의 인스턴스 매개 변수의 이름을 지정하고 다음을 수행 할 수 있습니다 :

def get_class_from_frame(fr): 
    import inspect 
    args, _, _, value_dict = inspect.getargvalues(fr) 
    # we check the first parameter for the frame function is 
    # named 'self' 
    if len(args) and args[0] == 'self': 
    # in that case, 'self' will be referenced in value_dict 
    instance = value_dict.get('self', None) 
    if instance: 
     # return its class 
     return getattr(instance, '__class__', None) 
    # return None otherwise 
    return None 

당신이 getargvalues를 사용하지 않으려면, 당신이 할 수있는 args 대신 value_dictframe.f_code.co_varnames[:frame.f_code.co_argcount] 대신 직접 frame.f_locals을 사용하십시오.

이 여전히 규칙에 의존하고 있다는 사실을 양지해야합니다, 그래서 휴대용하지 않고, 오류가 발생하기 쉬운 :

  • 첫 번째 매개 변수의 이름이 아닌 방법 기능을 사용 self 경우, get_class_from_frame 잘못 것 첫 번째 매개 변수의 클래스를 반환합니다.
  • 설명자로 작업 할 때 오해의 소지가 있습니다 (실제 인스턴스가 액세스되는 것이 아니라 설명자의 클래스를 반환합니다).
  • @classmethod@staticmethodself 매개 변수를 사용하지 않으며 설명자로 구현됩니다.
  • 확실

정확히 당신이 원하는 무엇에 따라 더 많은, 당신은 더 깊이 파고 이러한 모든 문제에 대한 해결 방법을 찾기 위해 시간이 걸릴 수도 있습니다 (당신은에 존재하는 프레임 기능을 확인할 수 있습니다 반환 된 클래스와 동일한 소스를 공유하고, 설명자 호출을 감지 할 수 있으며, 클래스 메서드와 동일합니다.)

+0

답변을 주셔서 감사합니다. Clément; 그것은 상세하고 사려 깊다. 나는 아직도 하나의 응답 이상을 얻고 싶습니다! 그러나 그렇지 않다면,이 것은 충분해야합니다 ... –

+0

OK, 오래 기다렸습니다. 이것은 좋은 대답입니다! 프레임 구조에서 더 나은 지원을 원했지만 그것이 그대로입니다. 다시 한 번 감사드립니다, Clément! –

+1

목록에 하나를 추가하려면 'self'가 파생 된 클래스의 인스턴스가 될 수 있습니다. 관심이없는 클래스 일 수 있습니다. – gertjan

7

이것은 조금 짧지 만 거의 같습니다. 클래스 이름을 사용할 수없는 경우 None을 반환합니다.

def get_class_name(): 
    f = sys._getframe(1) 

    try: 
     class_name = f.f_locals['self'].__class__.__name__ 
    except KeyError: 
     class_name = None 

    return class_name 
+0

좋은 답변입니다! 더 좋게는 f.f_locals [ '__ class __'] .__ name__''을 사용할 수 있습니다. 또한'@classmethod'와'@staticmethod''를 다루어야합니다. –

+2

@LucioPaiva가 작동하지 않습니다. f_locals에는 키''__class __ ''가 없습니다. – Pithikos

2

같은 문제에 직면했을 때 방금이 게시물을 보았습니다. 그러나 나는 이미 나열된 모든 이유로 '자기'방법을 수용 가능한 해결책이라고 생각하지 않았습니다.

다음 코드는 다른 접근법을 보여줍니다. 프레임 객체가 있으면 주어진 멤버 이름과 코드 블록과 일치하는 객체의 전역을 검색합니다. 검색은 거의 전체적으로 이루어지지 않으므로 모든 클래스가 밝혀지지 않을 수도 있지만 일치하는 코드를 확인하기 때문에 찾고있는 클래스가 있어야합니다. 코드의

개체를 찾을 경우, 해당 클래스 이름으로 함수 이름 앞에 추가하는 것입니다

def get_name(frame): 
    code = frame.f_code 
    name = code.co_name 
    for objname, obj in frame.f_globals.iteritems(): 
    try: 
     assert obj.__dict__[name].func_code is code 
    except Exception: 
     pass 
    else: # obj is the class that defines our method 
     name = '%s.%s' % (objname, name) 
     break 
    return name 

참고 __dict__ 대신 getattr의 사용은 파생 클래스의 잡기 방지하기 위해.

self = frame.f_locals['self']; obj = self.__class__이 일치하는 경우 또는 obj in self.__class__.__bases__ 이상인 경우 전역 검색을 피할 수 있으므로 최적화/하이브리드 화를위한 여지는 확실히 있습니다.

1

메소드가 클래스 메소드 인 경우, 클래스가 첫 번째 인수가됩니다. 각 호출 스택 프레임에 대한 첫 번째 arg 유형이 출력됩니다.

def some_method(self): 
     for f in inspect.getouterframes(inspect.currentframe()): 
      args, _,_, local_dict = inspect.getargvalues(f[0]) 
      if args: 
       first_arg = args[0] 
       first_value = local_dict[first_arg] 
       print(type(first_value).__name__) 
관련 문제