Python:将函数动态添加到类,其名称包含在字符串中

raj*_*han 2 python python-2.7

创建函数名包含为字符串的类的新成员函数的最佳方法是什么?此外,这个新函数仅仅是另一个对象(辅助类)的传递,它具有相同的函数名但具有可变参数.我使用lambda来实现这一点,但我不知道如何处理这个场景,我的传递包装器将不止一个语句(这是我的要求)

# This is a helper class
class Compensation:
   def bonus(self):
       return 10000
   def salary(self):
       # Do something
   def stack(self):
       # Do something

# This is a employer class
class employee:
   def __init__(self):
       self.compensation = Compensation()

# This is a wrapper that creates the function
def passThru(funcName):
    fn = "employee."+funcName+"=" + "lambda self, *arg: self.compensation." + funcName +"(*arg)"
    exec(fn)

fnNames = ["bonus", "salary", "stocks"]
for items in fnNames: passThru(items)

emp = employee()
emp.bonus() # returns 1000
Run Code Online (Sandbox Code Playgroud)

Tim*_*ers 5

所有这些诡计exec让我很头疼;-)我不清楚你想做什么,但添加一个名字由字符串给出的新方法真的很容易.例如,

class employee:
    pass

# Some multiline-function.
def whatever(self, a, b):
    c = a + b
    return c

e = employee()

# Make `whatever` an `employee` method with name "add".
setattr(employee, "add", whatever)
print e.add(2, 9)
Run Code Online (Sandbox Code Playgroud)

无论何时,只要你想要exec,你可能会错过一种直截了当的方式.

编辑:这里的一个奇怪的是,如果有人试图显示e.add,他们将得到一个声称其名称的字符串whatever.如果这困扰你,你可以添加,例如,

whatever.__name__ = "add"
Run Code Online (Sandbox Code Playgroud)

充实它

这更接近你想要的吗?请注意,@gnibbler提出了相同的建议,尽管更多的是电报:

class Compensation:
    def bonus(self, a):
        return 10000 + a
    def salary(self):
        return 20000
    def stack(self, a=2, b=3):
        return a+b

class employee:
    def __init__(self):
        self.comp = Compensation()


e = employee()

for name in "bonus", "salary", "stack":
    def outer(name):
        def f(self, *args, **kw):
            return getattr(self.comp, name)(*args, **kw)
        f.__name__ = name
        return f
    setattr(employee, name, outer(name))

print e.bonus(9)
print e.salary()
print e.stack(b="def", a="abc")
Run Code Online (Sandbox Code Playgroud)

显示:

10009
20000
abcdef
Run Code Online (Sandbox Code Playgroud)

总而言之,您可能想重新考虑您的架构.它很紧张.