在运行时如何将方法绑定到python中的对象?

时间:2015-11-27 05:34:44

标签: python monkeypatching setattr

我希望在运行时将一个方法添加到对象中。

class C(object):
  def __init__(self, value)
    self.value = value

obj = C('test')

def f(self):
  print self.value

setattr(obj, 'f', f)
obj.f()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 1 argument (0 given)

但似乎setattr没有将方法绑定到对象。有可能这样做吗?

3 个答案:

答案 0 :(得分:3)

您可以使用types模块中的MethodType

import types

obj.f = types.MethodType(f, obj)    
obj.f()

但你真的需要这个吗?寻找装饰器(例如),这是向课堂添加所需功能的更优雅方式。

答案 1 :(得分:1)

我发现使用locals()绑定空间和exec()命令。首先,您必须从内置的exec()创建一个函数对象并将其解压缩:

def make_function(name, parameter, commands):
    func = 'def {name}({parameter}):'.format(name=name,     parameter=parameter)
    for line in commands:
        func += '\n\t' + line
    exec(func)
    return locals()[name]

>>> func = make_function('help', 'pay', ['pay+=2', 'pay*=5', 'credit = pay//3', 'return credit'])
>>> func(8)
16

然后,您需要另一个使用 dict 属性创建实例对象的函数。对象的 dict 就像它的内部属性字典,可以通过。命令,它使python对象类似于javascript对象。

def create_object(names, values):
    assert len(names) == len(values)
    exec('class one: pass')
    obj = locals()['one']()
    for i in range(len(names)):
       obj.__dict__[names[i]] = values[i]
    return obj

>>> func = make_function('help', 'pay', ['pay+=2', 'pay*=5', 'credit = pay//3', 'return credit'])
>>> test_obj = create_object(['help', 'interest', 'message'], [func, 0.5, 'please pay by thursday.'])
>>> test_obj.help(7)
15
>>> test_obj.interest
0.5
>>> test_obj.message
'please pay by thursday.'

此函数实际上是拉链以将列表分开在一起,为您的实例对象创建一组属性。

答案 2 :(得分:1)

实际上,seattr不会将self / object传递给附加的方法 所以你能做的就是这样:

class C(object):
    def __init__(self, value):
        self.value = value

obj = C('some thing')


def make_method(_object, *args, **kwargs):
    def f(self=_object):
        print self.value
    return f

setattr(obj, 'f', make_method(obj))
obj.f()

它起作用,因为f()可以访问make_method()范围,因为它是内部/嵌套/闭包函数。