0

我有课:

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

4 回答 4

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()
于 2013-10-15T16:14:40.437 回答
1

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

在 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))    

请注意,这些包装方法......即两个函数都采用签名 likedef func(self, some, other, args)并且旨在被称为 like self.func(some, args)。如果要将类函数委托给非类函数,则需要修改委托者。

于 2013-10-15T15:25:41.717 回答
1

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

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

然后:

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

do_computing

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

于 2013-10-15T15:09:28.890 回答
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 ;)

希望这可以帮助!

于 2013-10-15T15:10:51.000 回答