我有一个自定义类,我在第二个类中实例化两次:
[编辑:旧代码并没有真正捕捉到我的问题,我正在重写以使其更清晰。 Foo将通过使用回调函数来处理网络事件(我需要多个连接,因此Bar将具有多个Foo字段并且不能仅继承)。在Bar类中,我想覆盖回调以执行不同的操作。在Foo中重写callb将不起作用,因为我在其他实例中继承了它]
class Foo(object):
def __init__(self, x):
self._x = x
#When an event happens, call callb()
self.on_certain_event(callback=callb)
def callb(self):
print self._x
def run(self):
waitForEventsInfinitely() #
class Bar(object):
def __init__(self):
self._foo = Foo(5)
#OVERWRITE THE EXISTING CALLBACK METHOD IN THE Foo CLASS!
self._foo.callb = self.callb
def callb(self):
print self._x * 10
def run(self):
waitForEventsInfinitely() # Not going to actually write t
f = Foo(2)
f.run()
b = Bar()
b.run()
[在Foo中调用run()时,它可以正常工作。但是,我不能用Bar覆盖Foo的callb方法 - 应该由Foo引用的self._x试图从Bar调用
然而,当运行代码时,我收到错误“Bar没有属性'_x'”,而不是我预期的值50.显然,Bar的测试中的self仍然指的是Bar,而不是实际的Foo调用方法。我本来以为它是Bar中的内部Foo self._foo字段。
我怀疑我的问题与名称修改有关,但是当我在自己的字段上覆盖了他们的方法时,我无法找到描述性的来源。大多数例子似乎都是在我从一个不同的类继承的时候。
答案 0 :(得分:1)
似乎在Bar.test中你想要:
print self._foo._x * 10
答案 1 :(得分:1)
关于Python中的类如何工作的简短课程:存储在类对象上的任何函数(“方法”)都由descriptor(它描述了如何从对象获取属性)自动获取,这些函数绑定了这些方法到你曾经得到它的类或实例。
例如:
Foo.test
是类Foo的未绑定方法:这是由Foo
上的描述符创建的对象,它知道它是从类对象中获取的
Foo().test
是类Foo 实例的绑定方法:此方法存储用于获取函数的Foo
实例。当您调用结果对象时,此实例将自动作为第一个参数传递,这就是您在定义方法时将self
作为第一个参数的原因。
所以,你要做的是:
test
获取原始函数Bar
(不是通过描述符)Foo
所以,你就是这样做的:
import types
class Bar(object):
def __init__(self):
self._foo = Foo(5)
raw_function = Bar.test_Bar.__func__ # 1)
bound_to_foo = types.MethodType(raw_function, self._foo) # 2)
self._foo.test = bound_to_foo # 3)
def test(self):
print self._x * 10
有关描述符的详细信息,请参阅this question。
答案 2 :(得分:0)
如果查看代码,当你调用b.test时,就是直接在Bar实例上调用该方法;根本没有提到Foo的实例。 b没有名为_x的成员,因此出错。要获得您期望的行为,您必须调用b._foo.test。这将为您提供50的预期结果。
如果您希望能够直接调用b.test,请将self._x更改为self._foo._x。这样您就不必更改_foo的任何方法。我不确定为什么你可以在你可以使用继承时为对象分配不同的方法。