将Python方法动态绑定到实例可以正确绑定方法名称,但不能绑定方法

2024-09-30 01:28:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一组RESTful服务编写客户机。REST调用的主体具有相同的XML结构(给定参数)。有几十个电话,我不会全部实现。我想让它们易于使用。REST方法在不同的模块中按功能分组,并且需要共享相同的urllib2开启器来进行身份验证和cookies。下面是一个如何声明方法的示例:

@rest_method('POST', '/document')
def createDocument(id, title, body):
    # possibly some validation on the arguments
    pass

开发人员所关心的就是验证。XML(用于POST和PUT)或URL(用于GET和DELETE)的格式以及响应的反序列化在helper方法中完成。修饰的方法被收集在一个客户机对象中,从中执行和处理它们。例如:

^{pr2}$

代码完成了。唯一的问题是将修饰的方法附加到客户机类。尽管所有修饰的方法都可以在客户机实例中看到,但它们都共享相同的定义,即最后一个要绑定的方法。下面是一个简单的例子,它复制了我看到的行为:

import types

class C(object): pass
def one(a): return a
def two(a, b): return a+b
def bracketit(t): return '(%s)' % t

c = C()

for m in (one, two):
    new_method = lambda self, *args, **kwargs:\
            bracketit(m(*args, **kwargs))
    method = types.MethodType(new_method, c, C)
    setattr(C, m.__name__, method)

print c.one 
print c.two
print c.two(1, 2)
print c.one(1)

运行此程序时,我得到以下输出:

<bound method C.<lambda> of <__main__.C object at 0x1003b0d90>>
<bound method C.<lambda> of <__main__.C object at 0x1003b0d90>>
(3)
Traceback (most recent call last):
  File "/tmp/test.py", line 19, in <module>
    print c.one(1)
  File "/tmp/test.py", line 12, in <lambda>
    bracketit(m(*args, **kwargs))
TypeError: two() takes exactly 2 arguments (1 given)

我不知道为什么这两种方法绑定在一起。关于instancemethod如何将方法绑定到实例,我还没有找到太多的文档。第二个引擎盖下面的指纹是怎么修复的?在


Tags: 方法lambdainrest客户机returnobjectdef
2条回答

lambda正在调用m,将其从本地作用域中拉出。在for循环结束后,m被设置为two。调用c.one或{}将导致{}被调用。在

通过查看回溯的最后一行,可以知道正在调用two

TypeError: two() takes exactly 2 arguments (1 given)

A good demonstration of what is going on can be found here.

这应该符合您的预期,但有点混乱:

^{pr2}$

我还删除了未绑定方法的显式创建,因为它是不必要的。在

问题是变量m在循环结束时保留为two,这会影响循环过程中的定义。可以通过使用嵌套函数创建闭包来修复它:

for m in (one, two):
    def make_method(m):
      def new_method(self, *args, **kwargs):
          return bracketit(m(*args, **kwargs))
      return new_method
    method = types.MethodType(make_method(m), c, C)
    setattr(C, m.__name__, method)

在测试代码中运行时生成:

^{pr2}$

相关问题 更多 >

    热门问题