2016-01-20 43 views
0

我知道在python中有一个名为decorator的东西,它可以比下面的代码更干净地完成工作。但我只是好奇为什么下面的代码不起作用。TypeError:bar()为关键字参数'_old'获取了多个值

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

def wrap(old, new): 
    "Override an existing function." 
    def repl(*args, **kwargs): 
     return new(_old=old, *args, **kwargs) 
    return repl 

class MyClass(object): 

    def foo(self, data): 
     print data 
     return data 

def bar(self, _old, data): 
    print 'running foo' 
    _old(data) 
    print 'foo completed' 

MyClass.foo = wrap(MyClass.foo, bar) 

mc = MyClass() 
mc.foo('Test Data') 

当我运行的代码,我得到了一个错误:

Traceback (most recent call last): 
    File "./test.py", line 24, in <module> 
    mc.foo('Test Data') 
    File "./test.py", line 7, in repl 
    return new(_old=old, *args, **kwargs) 
TypeError: bar() got multiple values for keyword argument '_old' 

有什么不对吗?我该如何解决它?

+0

为什么你的函数'bar'有一个参数'self'? – jacob

+0

问题可能是'自己'那里,也许这个答案在这里可以帮助http://stackoverflow.com/questions/18950054/class-method-generates-typeerror-got-multiple-values-for-keyword-argument – trainoasis

+0

@jacob因为'wrap'是为了用'bar'来代替'foo'。 'foo'有一个参数'self',所以'bar'应该有'self'参数。 – Searene

回答

1

有几个错误涉及缺少“自我”参数,并且您有关键字参数导致位置参数 - 它必须是相反的。试试这个(Python 3中,还原您认为合适的。):

def wrap(old, new): 
    "Override an existing function." 
    return lambda *args, **kwargs: new(*args, _old=old, **kwargs) 

class MyClass(object): 

    def foo(self, data): 
     print(data) 
     return data 

def bar(self, data, _old): 
    print('running foo') 
    _old(self, data) 
    print('foo completed') 

MyClass.foo = wrap(MyClass.foo, bar) 

mc = MyClass() 
mc.foo('Test Data') 

通过移动_old是在的位置参数结束并重新排列的号召,我们希望得到的东西的工作:

> python3 myclass.py 
running foo 
Test Data 
foo completed 
> 

我相信具体的错误“得到了关键字参数‘_old’由以下引起你调用‘吧’这样多个值:

新(_old =旧,* ARGS,** kwargs)

whic^h被重新安排到:

新(个体经营,数据,_old =旧)

(positionals导致关键字),但如果我们看酒吧的论点:

条(自我,_old,数据)

我们可以看到_old得到了两次,一次作为第二个位置参数,一次作为关键字参数。

部分困惑可能是Python有两个稍微不同但交互的'关键字参数'概念:通过关键字传递的位置参数;未指定的其他参数作为关键字传递。两人都在这里玩。

+0

谢谢!但还有一个问题我没有想到。为什么我应该把'_old'作为'bar'的最后一个参数? – Searene

+0

@Searene,我已经扩展了我的答案,尝试解决收到的具体错误消息,这可能会阐明为什么重新排列参数顺序可以修复此问题。 – cdlane

相关问题