我想从"red apple"
等字符串构造类。这将创建类 Apple
的实例,它是 Fruit
的子类。问题是,color
属性应该属于 Fruit
,而不是 Apple
。因此,在我看来,创建对象的自然方式是:
- 解析字符串
- 创建
Fruit(color="red")
- 创建
Apple()
- 以某种方式使其成为一个实体
到目前为止,我有 3 个选择:
一切都变成参数
class Fruit(object): def __init__(self, color): self.color = color def observe(self): print "Looks like a tasty %s fruit" % self.color @classmethod def fromstring(cls, string): color, kind = string.split() if kind == "apple": return Apple(color) class Apple(Fruit): def __init__(self, *args, **kwargs): super(Apple, self).__init__(*args, **kwargs) self.tasty = True def bite(self): print "I bite into a tasty apple" fruit = Fruit.fromstring("red apple")
color
属性是从外部填充的class Fruit(object): def observe(self): print "Looks like a tasty %s fruit" % self.color @classmethod def fromstring(cls, string): color, kind = string.split() if kind == "apple": ins = Apple() ins.color = color return ins class Apple(Fruit): def __init__(self): self.tasty = True def bite(self): print "I bite into a tasty apple" fruit = Fruit.fromstring("red apple")
最直接的方法:替换
__class__
class Fruit(object): def __init__(self, string): self.color, kind = string.split() if kind == "apple": self.__class__ = Apple Apple.__init__(self) def observe(self): print "Looks like a tasty %s fruit" % self.color class Apple(Fruit): def __init__(self): self.tasty = True def bite(self): print "I bite into a tasty apple" fruit = Fruit("red apple")
运行
fruit.observe()
fruit.bite()
print type(fruit), fruit.tasty
给出相同的输出:
Looks like a tasty red fruit
I bite into a tasty apple
<class '__main__.Apple'> True
第一种方法,可以说是最通用的,需要传递参数,例如 color
,在第三种方法中处理得更优雅。然而,改变 __class__
听起来像是使用高级工具来完成一项平凡的任务。是否有更好的方法来实现目标,或者我最好使用其中一种方法?
更新:我可能必须指出,在现实生活中,Fruit
和 Apple
的初始化器应该设置的属性数量是变量,总共约 15 个。
最佳答案
我会将创建逻辑完全从类中拉出来:
- 解析字符串
- 确定要创建的对象
- 创建对象
所以使用下面的代码:
class Fruit(object):
def __init__(self, color):
self.color = color
def observe(self):
print "Looks like a tasty %s fruit" % self.color
class Apple(Fruit):
def __init__(self,color):
super(Apple, self).__init__(color)
self.tasty = True
def bite(self):
print "I bite into a tasty apple"
fruit = None
color,type = "red apple".split()
if type == "apple":
fruit = Apple(color)
if type == "banana" and color == "blue"
raise Exception("Welcome to Chernobyl")
编辑:回复您对 dm03514 的回答的评论。
此代码与您的“选项 1”之间的主要区别在于,在此代码中,Fruit
不需要了解其子类。在我的代码中,我可以这样做:
class Banana(Fruit):
def __init__(self,color):
if color not in ["yellow","green"]:
raise Exception("Welcome to Chernobyl")
super(Banana).__init__(self,color)
if color = "yellow":
self.ripe = True
elif color = "green:"
self.ripe = False
def bite(self):
print "I bite into a %s banana"%["unripe","ripe"][self.ripe]
Fruit
不需要了解我的子类。在您的代码中,对于每种新类型的水果,Fruit
类都需要更新,这实际上限制了任何简单的扩展它的方法。如果您正在设计我想要的库,我无法重用 Fruit,因为我无法添加香蕉、橙子或任何您没有的水果,如果不更改您的代码,这与代码重用。
关于python - 如果子类由构造逻辑确定,那么分离类及其父类逻辑的最pythonic和优雅的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18971275/