我不是一个非常伟大或经验丰富的Python编码员,我想知道是否有一种简单的方法来做我需要做的事情。但是我还没能自己找到任何东西,因为我不知道如何正确地表达这个问题。
我的情况大致如下:
class Insect:
def __init__(self, arg1):
self.arg1 = arg1
def insect_method(self):
print('do insect stuff')
class Caterpillar(Insect):
def __init__(self, arg1):
super().__init__(arg1)
def caterpillar_method(self):
print('do caterpillar stuff')
class Butterfly(Insect):
def __init__(self, arg1, arg2):
super().__init__(arg1)
self.arg2 = arg2
def butterfly_method(self):
print('do butterfly stuff')
我实际上并没有模拟毛毛虫和蝴蝶,但这是一个类似的过程,所以我认为这可能有助于使事情更清楚。
我有一个超类'Insect',它从来没有被自己创建,但存在,所以子类可以继承它的方法。大多数时候,我只是直接生成子类,就是这样。但是我有一个特殊的情况,Caterpillar子类应该成为Butterfly子类的一个实例。
我已经搜索过了,并且确信改变__class__
可能不是我长期想做的事情。然而,我也不确定是否有一种优雅的方式来做到这一点。
目前我能想到的唯一技术是添加一堆if
语句,像这样:
class Insect:
def __init__(self, arg1):
self.arg1 = arg1
def insect_method(self):
print('do insect stuff')
class Caterpillar(Insect):
def __init__(self, arg1):
super().__init__(arg1)
def caterpillar_method(self):
print('do caterpillar stuff')
class Butterfly(Insect):
def __init__(self, arg1, arg2, caterpillar=None):
if not caterpillar:
super().__init__(arg1)
else:
self.arg1 = caterpillar.arg1
self.arg2 = arg2
def butterfly_method(self):
print('do butterfly stuff')
如果实际代码像这样简单,这将起作用,但事实并非如此,所以我最终不得不在Butterfly.__init__
方法中制作一种Insect.__init__
方法的double,然后必须确保在Insect.__init__
方法中更改任何内容时不断更新这两个方法。
__init__
方法?提前感谢!!
而不是把这个逻辑放在你的__init__
,我可能会保持__init__
简单,并把逻辑从Caterpillar
创建Butterfly
在classmethod
:
class Butterfly(Insect):
def __init__(self, arg1, arg2):
super().__init__(arg1)
self.arg2 = arg2
@classmethod
def from_caterpillar(cls, caterpillar, arg2):
return cls(caterpillar.arg1, arg2)
那么你可能会有这样的代码:
bob = Caterpillar("Bob")
# metamorphose
bob = Butterfly.from_caterpillar(bob, "Small")
请注意,与原始代码类似,这不会改变原始Caterpillar
对象使其成为Butterfly
,它创建了一个新的Butterfly
实例(并将bob
重新分配给它)。
这里有两个不同的概念:蝴蝶是物种,蝴蝶是该物种生活方式的成年阶段。在具有线性类型的纯函数式语言中,您可能有一个函数,它接受一只毛毛虫,产生一只蝴蝶,和确保您不能再使用该毛毛虫实例。
在Python中,我可以定义以下类:from abc import ABC, abstractmethod
class Stage(ABC):
@abstractmethod
def do_something(self):
...
class Caterpillar(Stage):
def do_something(self):
print("do caterpillar stuff")
class AdultButterfly(Stage):
def do_something(self):
print("do butterfly stuff")
class Butterfly(Insect):
def __init__(self):
self.stage = Caterpillar()
def do_something(self):
return self.stage.do_something()
def growup(self):
self.stage = AdultButterfly()
这允许Butterfly
实例从毛毛虫到(成年)蝴蝶的转换,而不需要
- 从无到有创造一只成年蝴蝶,或
- 从一只毛毛虫产生多只成年蝴蝶
有几种方法可以做到这一点。可能是最易读和"干净"的;(好吧…至少对我来说)是@classmethod
s:要么通过@Samwise在另一个答案中提出的Butterfly
中的from_caterpillar
类方法,要么在您的Caterpillar
中使用@Pranav Hosangadi在其中一个评论中提出的become_butterfly
类方法。
我只是想给你介绍一下isinstance方法。
如果你能让Butterfly
的构造函数接受一个"whatever"或者将Caterpillar
的实例作为arg1
,您可以执行如下操作:
class Butterfly(Insect):
def __init__(self, arg1, arg2):
if isinstance(arg1, Caterpillar):
print("OMG! Metamorphosed!! Digievolution!")
super().__init__(arg1.arg1)
# Or just:
# self.arg1 = arg1. arg1
else:
super().__init__(arg1)
self.arg2 = arg2