代码之家  ›  专栏  ›  技术社区  ›  Kevin Little

Python:如何从“frame”对象检索类信息?

  •  16
  • Kevin Little  · 技术社区  · 16 年前

    是否可以从框架对象检索任何类信息?我知道如何获取文件(frame.f_code.co_filename)、函数(frame.f_code.co_name)和行号(frame.f_lineno),但我也希望能够获取帧的活动对象实例的类的名称(或者如果不在实例中,则无)。

    4 回复  |  直到 16 年前
        1
  •  24
  •   Clément    16 年前

    我不相信,在框架对象级别,有任何方法可以找到已调用的实际python函数对象。

    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 frame.f_locals 而不是 value_dict frame.f_code.co_varnames[:frame.f_code.co_argcount] 而不是 args

    请记住,这仍然只依赖于约定,因此它不可移植,并且容易出错:

    • 自己 作为第一个参数名,然后 get_class_from_frame 将错误地返回第一个参数的类。
    • @classmethod @staticmethod 参数和使用描述符实现。
    • 当然还有更多

        2
  •  8
  •   Ruslan    16 年前

    这有点短,但大致相同。如果类名不可用,则返回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
    
        3
  •  6
  •   Graham Dumpleton    13 年前

    下面的代码演示了一种不同的方法:给定一个框架对象,它在全局搜索具有匹配成员名称和代码块的对象。搜索很难穷尽,因此可能不会发现所有的类,但找到的类应该是我们正在寻找的类,因为我们验证匹配的代码。

    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__

        4
  •  1
  •   oz123    9 年前

        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__) 
    
        5
  •  0
  •   Liebranca    5 年前

    你好,原谅necro;但这些对我来说都不管用,因为这里的一些片段激发了我的灵感,我想出了另一个选择。这就是我在python 3.7中为类方法所做的工作:

    import inspect;
    
    def QLNAME(frame):
    
        code = frame.f_code;
        name = code.co_name;
        qual = None;
    
        for cls in ( obj for obj in frame.f_globals.values()  #
                         if  inspect.isclass(obj)             ):
    
            if hasattr(cls, name):
    
                member = getattr(cls, name);
                if not inspect.isfunction(member): continue;
    
                if member.__code__ == code:
                    qual = member.__qualname__;
                    break;
    
        return qual;
    

    我们检查,它的工作方式实际上非常简单

    1. 如果该类有一个成员共享有问题的名称

    如果N4是真的,那么我们知道一个事实 cls 是一个具有某种方法的类 member

    但请注意,这是 非常

    希望在这里搜索引擎遇到问题的其他人能找到一些有用的东西。

    干杯