我知道python中有一种叫做decorator
的东西,它可以比下面的代码更整齐地完成这项工作。但我只是好奇为什么以下代码不起作用。
#!/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'
这是怎么回事?我该如何解决它?
有几个错误涉及缺少"self"参数,并且你有关键字参数引导位置参数 - 它必须是相反的方式。 试试这个(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'有多个值是由以下原因引起的。 你这样调用"bar":
new(_old=old, *args, **kwargs)
它被重新排列成:
new(self, data, _old=old)
(位置引导关键字)但如果我们看一下 bar 的论点:
条形图(自_old条形图、数据条形图)
我们可以看到_old被传递了两次,一次作为第二个位置参数,一次作为关键字参数。
部分混淆可能是Python有两个略有不同但相互作用的"关键字参数"概念:通过关键字传递的位置参数;作为关键字传递的未指定的附加参数。 两者都在这里发挥作用。