我有这样的代码:
class Person(object):
def drive(self, f, t):
raise NotImplementedError
class John(Person):
def drive(self, f, t):
print "John drove from %s to %s" % (f,t)
class Kyle(Person):
def drive(self, f, t):
print "Kyle drove from %s to %s" % (f,t)
class RandomPerson(Person):
# instansiate either John or Kyle, and inherit it.
pass
class Vehicle(object):
pass
class Driver(Person, Vehicle):
def __init__(self):
# instantiate and inherit a RandomPerson somehow
pass
d1 = Driver()
d1.drive('New York', 'Boston')
>>> "John drove from New York to Boston"
d2 = Driver()
d2.drive('New Jersey', 'Boston')
>>> "Kyle drove from New Jersey to Boston"
我如何在满足以下要求的情况下实现随机人:
RandomPerson
应该随机地子类John
或{
在我最初的回答中(我删除了它,因为它是完全错误的)我说我会考虑这样做:
这种方式是Python Borg idiom的一种改编;其思想是,与对象有关的所有重要内容都包含在它的
__dict__
中。在但是,这只在覆盖同一个类的对象时才有效(这是您在Borg习惯用法中所做的);对象
__dict__
只包含与对象实例相关的状态信息,而不是对象类。在可以这样切换对象的类:
^{pr2}$但是,这样做意味着对}的实例。所以这是不可能的。在
RandomPerson
的调用不会根据您的要求返回RandomPerson
的实例,而是返回Kyle
或{下面是一种获取},但不是:
RandomPerson
对象的方法,该对象的行为类似于Kyle
或{这一个非常类似于Borg习惯用法,除了用类而不是实例对象来做,而且我们只复制了所选类dict的当前版本,这是非常邪恶的:我们已经将
RandomPerson
类进行了分块,并且(随机地)将Kyle
或John
类的大脑固定在适当的位置。不幸的是,没有迹象表明发生了这种情况:所以我们仍然没有真正的子类}。而且,这真的很邪恶。所以除非你有充分的理由,否则请不要这么做。在
Kyle
或{现在,假设您确实有一个很好的理由,如果您所追求的是确保可以使用}中的任何类状态信息(方法和类属性),那么上面的解决方案就足够了。然而,如前所述,
Kyle
或{RandomPerson
仍然不是其中一个真正的子类。在正如我所知,没有办法在实例创建时随机地将一个对象的类划分为子类,也没有办法让该类在多个实例创建过程中保持状态。你得假装一下。在
伪造它的一种方法是允许使用abstract baseclass module and ^{} 将}的子类,并将其添加到您的
RandomPerson
视为John
和{Person
类中。这看起来是一个很好的解决方案,因为Person
类是一个接口,无论如何不会被直接使用。在有一种方法可以做到:
现在}的子类,并且它也共享}被实例化时,}都可以是})。在
RandomPerson
-尽管它在技术上不是一个子类,但它被认为是Kyle
或{Kyle
或John
的状态。事实上,每次创建一个新实例(或者RandomPerson.identity
被更改)时,它将在这两个实例之间随机地来回切换。这样做的另一个效果是:如果您有多个RandomPerson
实例,它们都共享该时刻RandomPerson
的状态,即,rperson1
可能开始是Kyle
,然后当{rperson2
和{John
(或者它们都可以是Kyle
,然后在创建rperson3
时切换到{不用说,这是很奇怪的行为。事实上,这太奇怪了,我怀疑你的设计需要彻底检修。我真的不认为有一个很好的理由去做这件事(除了和别人开个坏玩笑)。在
如果不想将此行为混合到
Person
类中,也可以单独执行:您只需实现
RandomPerson
类,就可以拥有一个名为_my_driver
的成员或任何您想要的东西。您只需从RandomPerson.drive
方法调用他们的drive
方法。它可能看起来像这样:或者,如果您想更严格地确保类与
^{pr2}$Kyle
或John
具有完全相同的方法,可以在构造函数中设置如下方法:你在你的most recent comment on my other answer中说:
如果我可以这么说,这是一个奇怪的选择。首先,在创建对象之后交换类似乎不是很简单(这太复杂了)。最好是随机生成对象实例,而不是事后指定类:
其次,如果代码已经过重构,因此不再需要
^{pr2}$RandomPerson
对象,那么为什么还要这样呢?只需使用工厂函数:相关问题 更多 >
编程相关推荐