Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可在父类外部调用的Python装饰方法_Python_Decorator - Fatal编程技术网

可在父类外部调用的Python装饰方法

可在父类外部调用的Python装饰方法,python,decorator,Python,Decorator,假设我有一个类用作装饰器,如下所示: class specialmethod: def __init__(self,func): self.func = func def __call__(self,arg1,arg2): print arg1,arg2 self.func(arg1,arg2) 但是被修饰的方法在另一个类中,该类也必须使用self(self中的值与修饰后的函数体相关) A类: @特殊方法 def剂量测量(自身、数据、其他数据): #下面

假设我有一个类用作装饰器,如下所示:

class specialmethod:
  def __init__(self,func):
     self.func = func

  def __call__(self,arg1,arg2):
     print arg1,arg2
     self.func(arg1,arg2)
但是被修饰的方法在另一个类中,该类也必须使用
self
(self中的值与修饰后的函数体相关)

A类:
@特殊方法
def剂量测量(自身、数据、其他数据):
#下面这个家伙没有得到self的正确值,一个
打印类型(自身)
回溯(最近一次呼叫最后一次):
文件“deco.py”,第18行,在
a、 dosomething('foo','bar')
调用中第7行的文件“deco.py”__
self.func(arg1、arg2)
TypeError:dosomething()正好接受3个参数(给定2个)
如果没有装饰的话,
self
的工作方式还有保留吗?我已经尝试显式地传递它,但它仍然需要错误数量的参数

编辑


我应该澄清,
dosomething
的最终函数体中self的预期值应该参考
A
的实例。。。不希望将decorator实例放入修饰函数中。

当您使用像decorator这样的类时,您必须意识到,将函数转换为方法(描述符协议,特别是
\uuu get\uuuu
方法)的正常魔力对于您的类不起作用,除非您显式地实现它。您可以通过实现一个
\uuuuu get\uuuuu
方法手动执行此操作,该方法返回一个新类型,该类型将记住从中检索到的实例以及要调用的实际可调用实例,但这需要大量的工作,但收获甚微

一种更常见的方法是不使用实际的类作为装饰器,而总是让装饰器返回实际的Python函数。在这种特殊情况下,保留类实际上没有任何意义,因此您可以执行以下操作:

def specialmethod(f):
    @functools.wraps(f)
    def wrapper(arg1, arg2):
        print arg1, arg2
        f(arg1, arg2)
    return wrapper
。。。但如果你真的想保住这个班,你可以做如下事情:

class _specialmethod:
  def __init__(self,func):
     self.func = func

  def __call__(self,arg1,arg2):
     print arg1,arg2
     self.func(arg1,arg2)

def specialmethod(f):
    wrapper_class = _specialmethod(f)
    @functools.wraps(f)
    def wrapper(arg1, arg2):
        wrapper_class(arg1, arg2)
    return wrapper

即使被修饰的函数是类中的方法,第一个方法仍然有效吗?这两个参数之前的附加
self
?如果要修饰的函数是类中的方法,则这两种方法都有效;在这两种情况下,
arg1
是接收实例的参数,即包装函数中的
self
。(我从您的示例中复制了命名,但通常您在包装器定义和对
f
的调用中都使用
*args,**kwargs
。在这种情况下,
self
args
元组中的第一项。)效果很好,谢谢!最后一个问题是,如果被修饰的方法是
A
的神奇方法之一,比如
\uuuuu调用\uuuuuuuu
,行为会有所不同吗?不,装饰器返回函数意味着结果是一个完全常规的Python版本,Python无法区分原始函数和修饰函数之间的区别。它的工作原理完全相同。为什么需要functools.wrapps?
class _specialmethod:
  def __init__(self,func):
     self.func = func

  def __call__(self,arg1,arg2):
     print arg1,arg2
     self.func(arg1,arg2)

def specialmethod(f):
    wrapper_class = _specialmethod(f)
    @functools.wraps(f)
    def wrapper(arg1, arg2):
        wrapper_class(arg1, arg2)
    return wrapper