在运行时如何将方法绑定到 python 中的对象?
How do you bind methods to objects in python during runtime?
我想在运行时向对象添加一个方法。
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并没有把方法绑定到对象上。可以这样做吗?
我发现有一种方法,使用 locals() 绑定 space 和 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.'
这个函数本质上是将单独的列表压缩在一起,为您的实例对象创建一组属性。
您可以使用 types 模块中的 MethodType
:
import types
obj.f = types.MethodType(f, obj)
obj.f()
但你真的需要这个吗?寻找装饰器(例如),这是向 class.
添加所需功能的更优雅的方式
事实上,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()
作用域,因为它是一个 inner/nested/closure 函数。
我想在运行时向对象添加一个方法。
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并没有把方法绑定到对象上。可以这样做吗?
我发现有一种方法,使用 locals() 绑定 space 和 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.'
这个函数本质上是将单独的列表压缩在一起,为您的实例对象创建一组属性。
您可以使用 types 模块中的 MethodType
:
import types
obj.f = types.MethodType(f, obj)
obj.f()
但你真的需要这个吗?寻找装饰器(例如),这是向 class.
添加所需功能的更优雅的方式事实上,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()
作用域,因为它是一个 inner/nested/closure 函数。