如何在python中的两个不同类上共享相同的方法

时间:2013-10-15 15:01:06

标签: python typeclass

我上课了:

class A(object):
    def do_computing(self):
        print "do_computing"

然后我有:

new_class = type('B', (object,), {'a': '#A', 'b': '#B'})

我想要实现的是使类A上的所有方法和属性成为类B的成员。类A可以具有0到N个这样的元素。我想让他们都成为B班的一员。

到目前为止,我接受了:

methods = {}

for el in dir(A):
    if el.startswith('_'):
        continue

    tmp = getattr(A, el)

    if isinstance(tmp, property):
        methods[el] = tmp

    if isinstance(tmp, types.MethodType):
        methods[el] = tmp

instance_class = type('B', (object,), {'a': '#A', 'b': '#B'})

for name, func in methods.items():
    new_method = types.MethodType(func, None, instance_class)
    setattr(instance_class, name, new_method)

但是当我跑步时:

instance().do_computing()

我收到错误:

TypeError: unbound method do_computing() must be called with A instance as first argument (got B instance instead)

为什么我必须这样做?我们有很多遗留代码,我需要花哨的对象,假装它们是旧对象,但实际上。

还有一件重要的事情。我不能使用继承,在背景中会发生很多魔法。

4 个答案:

答案 0 :(得分:2)

如果您这样做,它将起作用:

import types

class A(object):
    def do_computing(self):
        print "do_computing"

methods = {name:value for name, value in A.__dict__.iteritems()
                        if not name.startswith('_')}

instance_class = type('B', (object,), {'a': '#A', 'b': '#B'})

for name, func in methods.iteritems():
    new_method = types.MethodType(func, None, instance_class)
    setattr(instance_class, name, new_method)

instance_class().do_computing()

答案 1 :(得分:1)

除非我遗漏了什么,否则你可以通过继承做到这一点:

class B(A):
    def __init__(self):
        super(B, self).__init__()

然后:

>>> b = B()
>>> b.do_computing()

do_computing

编辑:cms_mgr在评论中说同样,也修复了缩进

答案 2 :(得分:1)

你正在创造一个立面吗?也许你想要这样的东西:

Making a facade in Python 2.5

http://en.wikipedia.org/wiki/Facade_pattern

你也可以使用委托人。这是wxpython AGW的一个例子:

_methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList", "GetStateImageList",
        "GetButtonsImageList", "AssignImageList", "AssignStateImageList", "AssignButtonsImageList",
        "SetImageList", "SetButtonsImageList", "SetStateImageList", 'other_methods']

def create_delegator_for(method):
"""
Creates a method that forwards calls to `self._main_win` (an instance of :class:`TreeListMainWindow`).

:param `method`: one method inside the :class:`TreeListMainWindow` local scope.
"""

    def delegate(self, *args, **kwargs):
        return getattr(self._main_win, method)(*args, **kwargs)
    return delegate

# Create methods that delegate to self._main_win. This approach allows for
# overriding these methods in possible subclasses of HyperTreeList
for method in _methods:
    setattr(HyperTreeList, method, create_delegator_for(method))    

请注意,这些包装方法......即两个函数都采用def func(self, some, other, args)之类的签名,并且打算像self.func(some, args)一样调用。如果要将类函数委托给非类函数,则需要修改委托者。

答案 3 :(得分:0)

您可以从父类继承:

class Awesome():

    def method_a():
        return "blee" 


class Beauty(Awesome):

    def __init__(self):
        self.x = self.method_a()

b = Beauty()
print(b.x)
>>> "blee"

这是自由输入的,但逻辑是相同的,并且应该工作。

你也可以像setattr一样做有趣的事情:

#as you can see this class is worthless and is nothing 
class blee():
    pass 

b = blee()
setattr(b, "variable_1", "123456")
print(b.variable_1)
>>> 123456

基本上你可以使用setattr将任何对象,方法分配给类实例。

编辑:刚才意识到你确实使用了setattr,woops;)

希望这有帮助!