我上课了:
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)
为什么我必须这样做?我们有很多遗留代码,我需要花哨的对象,假装它们是旧对象,但实际上。
还有一件重要的事情。我不能使用继承,在背景中会发生很多魔法。
答案 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)
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;)
希望这有帮助!