在Python 3中从字符串定义方法并作为方法引用

时间:2018-07-19 13:42:36

标签: python python-3.x python-exec

我需要允许用户定义一个处理对象中数据的功能(在另一个问题中详细讨论了其中的智慧和安全性,这里只是重复的注释。)

我希望该函数像其他任何方法一样起作用。那是

def my_method(self):...

将被调用:

obj_handle.my_method()

除了需要将结果self作为参数显式传递,而不是像通常方法一样将其作为第一个参数接收,我在下面几乎实现了这一目标。

您可以在属性p中看到此消息,在这里我有奇怪的self.process(self)呼叫。

我想我需要向exec提供一些类似于globals()字典的内容,但是我不确定其中几件事:

  1. 这正确吗?
  2. 课程中globals()的等效项是什么?
  3. 这可以解决问题吗?如果没有,我该怎么办?

问题是,如何获得一个exec()定义的函数以充当对象的方法?

class test:
   def __init__(self, a, b):
       self.a=a
       self.b=b

   @property
   def p(self):
       return self.process(self)

   def set_process(self,program):
       func_dict={}
       proc_fun = exec(program,func_dict)
       setattr(self,'process',func_dict['process'])

   def process(self):
       return self.a+self.b

t=test(1,2)
prog = '''\
def process(self):
    return self.a * self.b
'''

t.set_process(prog)
t.p

2 个答案:

答案 0 :(得分:2)

上面@ juanpa.arrivillaga的评论中回答:

如果您希望其描述符协议起作用并在实例上调用时绑定tye实例,请在该类上设置该函数。因此,一种解决方案只是将set_process设为类方法。 – 1小时前juanpa.arrivillaga

工作结果

class test:
    def __init__(self, a, b):
        self.a=a
        self.b=b

    @property
    def p(self):
        return self.process()

    @classmethod
    def set_process(cls,program):
        func_dict={}
        proc_fun = exec(program,func_dict)
        setattr(cls,'process',func_dict['process'])

    def process(self):
        return self.a+self.b

t=test(1,2)
prog = '''\
def process(self):
    return self.a * self.b
'''

test.set_process(prog)
t.p

答案 1 :(得分:1)

如果要操作实例而不是类:

import types

class Test:

    def __init__(self, a, b):
        self.a = a
        self.b = b

    @property
    def p(self):
        return self.process()

    def set_process(self, program):
        d = dict()
        exec(program, d)
        self.process = types.MethodType(d["process"], self)

    def process(self):
        return self.a + self.b

prog = '''\
def process(self):
    return self.a * self.b
'''

t = Test(1, 2)
t.set_process(prog)
print(t.p)

t = Test(1, 2)
print(t.p)