基于Python标准的动态函数添加到类中

时间:2012-02-28 09:17:00

标签: python metaprogramming python-2.7 python-2.6 python-2.x

如何根据某些条件动态地向类中添加函数。

对于ex,我有一个类作为follwos:

class A(object):
     def __init__(self,type):
         self.type = type

现在基于'type'值我希望将类B或C类的函数添加到A类。

对于前。

lass B(object):
    def fun1(self):
        print 'fun1'
    def fun2(self):
        print 'fun2'

class C(object):
    def fun3(self):
        print 'fun3'
    def fun4(self):
        print 'fun4'

如果类A的'type'属性值为'B',则将类B的函数(即fun1和fun2)动态添加到类A,否则如果'type'属性值为'C',则添加类C的函数到A类(即fun3和fun4)到A类,这样在我的代码中我可以访问这些函数,如A.fun1()或A.fun3。

我猜这个元编程可能会让我知道这一点,但我不知道如何做到这一点。请指导。

此外,我必须创建A类对象,并能够通过A类对象使用这些函数。

a = class A(type='B')
a.fun1()  #should work

请帮忙,因为我无法弄清楚这一点。

这是我的代码的一部分。

class Group(object):
    def __init__(self,type):
        if type == 'source'
            self.mgr = SManager(self)             #grp_mgr
        elif type == 'target'
            self.mgr = TManager(self)

    def __getattr__(self,name):
        if hasattr(self.mgr,name):
            return getattr(self.mgr,name)
        return AttributeError

class SManager(object):
    def __init__(self,groupobj):
        self.some_list = []
        self.groupobj = groupobj

    def doProcess(self):
        #this function accesses self.groupobj
        pass

    def get_valid_list(self):
        #this function accesses self.groupobj
        pass

但是有了这个我得到以下错误。

    if hasattr(self.mgr,name):
  File "c:\workspace\project\dev.py", line 27, in __ge
tattr__
    if hasattr(self.mgr,name):
  File "c:\workspace\project\dev.py", line 27, in __ge
tattr__
    if hasattr(self.mgr,name):
  File "c:\workspace\project\dev.py", line 27, in __ge
tattr__
    if hasattr(self.mgr,name):
  File "c:\workspace\project\dev.py", line 27, in __ge
tattr__
    if hasattr(self.mgr,name):
  File "c:\workspace\project\dev.py", line 27, in __ge
tattr__
    if hasattr(self.mgr,name):
RuntimeError: maximum recursion depth exceeded while calling a Python object

我无法弄清楚我在哪里弄错了。在合并之前我尝试使用一个简单的代码片段,但是当我在实际代码中执行相同操作时,它会抛出错误。 请帮忙

3 个答案:

答案 0 :(得分:3)

好像你的问题是XY Problem,原始问题“X”的解决方案是多重继承,例如:

class A(B, C):
    pass

现在,您可以A().fun1()以及A().fun3()

答案 1 :(得分:1)

Roman的回答可能是最认真的方法。但是,嘿,让我们忽略这一点,想想你可以做的一些疯狂的事情!

你可以使用一个功能,但这太容易了:

def A(type):
    if type == 'B':
        return B()
    elif type == 'C':
        return C

您可以覆盖__getattr__,以便在所选类的实例上查找缺少的属性:

class A(object):
    def __init__(self, type):
        if type == 'B':
            self.type = B()
        if type == 'C':
            self.type = C()

    def __getattr__(self, name):
        if hasattr(self.type, name):
            return getattr(self.type, name)
        return AttributeError

或者你可以覆盖__new__,并返回一个疯狂的新类,或者你感兴趣的类的实例:

class A(object):
    bases = {'B': B, 'C': C}

    def __new__(cls, type):
        class Cls(A.bases[type]):
            pass
        return Cls()

可能还有很多其他被误导的事情!

答案 2 :(得分:1)

正如我在问题评论中已经说过的那样:你可能根本不需要元类。

但是既然你没有提供更多信息,那么你可以用元类来解决这个问题:

class MetaX(type):

    def __add__(cls, other):
        name = '{}+{}'.format(cls.__name__, other.__name__)
        return type(cls)(name, (cls, other), dict())


class X(object):    # metaclass=MetaX in py3k

    __metaclass__ = MetaX

    def __add__(self, other):
        cls = type(self) + type(other)
        return cls

就是这样,你只需要继承X

示例:

class A(X):
    def func_a(self):
        print "I'm in func_a"

class B(X):
    def func_b(self):
        print "I'm in func_b"

class C(X):
    def func_c(self):
        print "I'm in func_c"

L = A + B
l = L()
l.func_a()  # -> I'm in func_a
l.func_b()  # -> I'm in func_b

P = A + C
p = P()
p.func_a()  # -> I'm in func_a
p.func_c()  # -> I'm in func_c

编辑:您真正需要的内容取决于您的实际代码的样子。

你在问题​​中描述的是一个动态继承,如果这是你真正需要的,那么IMO一个元类是正确的工具并覆盖__getattr__它只是一个黑客。

如果你不想构建一个完整的元类,你可以构建只使用某种类工厂:

def get_enhanced_A(typ)   # you can't use type as a keyword here
    dct = {'B': B, 'C': C}
    return type('A+{}'.format(typ), (A,dct[typ]), dict())

我不知道这两个选项中的哪一个看起来更好。