【问题标题】:Get the class name of a decorated class method获取装饰类方法的类名
【发布时间】:2011-07-01 19:17:21
【问题描述】:

考虑这种情况:

import functools

def wrapmethod(f):
    @functools.wraps(f)
    def wrap(*args, **kwargs):
        print '>> %s' % (f.func_name)

        # Here I'll do pre-processing
        r = f(*args, **kwargs)
        # Here I'll do post-processing

        return r

    return wrap

@wrapmethod
def foo():
    pass

class Test(object):
    @wrapmethod
    def foo(self):
        pass

test = Test()
test.foo()
foo()

它会输出这个,正如你在http://codepad.org/Y4xXyjJO中看到的那样:

>> 富
>> 富

我想知道一种在第一行打印出Test.foo 的方法,表明该方法链接到的类。

有什么想法吗?有可能吗?

提前谢谢你。

【问题讨论】:

    标签: python decorator


    【解决方案1】:

    其实你可以使用inspect模块来获取函数的签名,假设你遵循第一个参数'self'引用类对象的约定,你可以这样做:

    import inspect  
    def print_name(*_args):
        def _print_name(fn):
            def wrapper(*args, **kwargs):
                try :
                    is_method   = inspect.getargspec(fn)[0][0] == 'self'
                except :
                    is_method   = False
    
                if is_method :
                    name    = '{}.{}.{}'.format(fn.__module__, args[0].__class__.__name__, fn.__name__)
                else :
                    name    = '{}.{}'.format(fn.__module__, fn.__name__)
    
                print (name)
                return  fn(*args,**kwargs)
            return wrapper
        return _print_name
    

    如果这是一个函数,这将打印方法模块、类和名称或者只是模块和名称

    从 python 3.3 开始,fn.__qualname__ 可用于获取函数/方法的限定名。

    def print_name(*args):
         def _print_name(fn):
             def wrapper(*args, **kwargs):
                 print('{}.{}'.format(fn.__module__, fn.__qualname__))
                 return fn(*args, **kwargs)
             return wrapper
         return _print_name
    

    这适用于函数和方法:

    In [1]: class A():
    ...:     @print_name()
    ...:     def a():
    ...:         print('Hi from A.a')
    In [2]: A.a()
        __main__.A.a
        Hi from A.a
    
    In [25]: @print_name()
        ...: def b():
        ...:     print('Hi from b')
        ...: 
    In [26]: b()
        __main__.b
        Hi from b
    

    【讨论】:

      【解决方案2】:

      这并不容易。 如果您将self 添加为内部函数的第一个参数,您可以使用self.__class__.__name__ 来访问类名,但是在装饰没有参数的无类函数时它会中断(如果它有参数,它会考虑第一个参数为self)。

      因此,除非有办法确定函数是否已在对象上下文中调用,否则您想要做的事情是不可能的。

      顺便说一句..你需要什么?这听起来像是可以用更好的方式解决的问题。

      【讨论】:

      • 好吧,我编写了这种方法来在我的代码中进行时间分析,因此我可以将处理方法包装在启动和停止计时器中。我主要在类方法中需要它,所以我认为这个 self 参数已经足够好了。谢谢你的提示!欢迎您提出建议。 :)
      【解决方案3】:

      一个简单的版本:

      def print_my_location(func):
          def wrapper(*args, **kwargs):
              print(f'[{func.__module__}::{func.__qualname__}]: ')
              return func(*args, **kwargs)
      
          return wrapper
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-14
        • 1970-01-01
        • 2020-01-02
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 2014-12-07
        相关资源
        最近更新 更多