Python 什么';如果子类是由构造逻辑决定的,那么将类的逻辑与其父类的逻辑分开的最简洁、最优雅的方法是什么?
我想从字符串中构造类,比如Python 什么';如果子类是由构造逻辑决定的,那么将类的逻辑与其父类的逻辑分开的最简洁、最优雅的方法是什么?,python,class,inheritance,Python,Class,Inheritance,我想从字符串中构造类,比如“redapple”。这将创建类Apple的实例,它是Fruit的子类。问题是,颜色属性应该属于水果,而不是苹果。因此,在我看来,创建对象的自然方式似乎是: 解析字符串 创建水果(color=“red”) 创建Apple() 以某种方式使它成为一个单一的实体 到目前为止,我有3种选择: 一切都变成了参数 class Fruit(object): def __init__(self, color): self.color = color
“redapple”
。这将创建类Apple
的实例,它是Fruit
的子类。问题是,颜色
属性应该属于水果
,而不是苹果
。因此,在我看来,创建对象的自然方式似乎是:
Apple()
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")
\uuuuu类
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
之类的参数,而第三种方法处理这些参数要优雅得多。然而,改变\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
听起来就像是在为。有没有更好的方法来实现目标,或者我最好使用其中一种方法
更新:我可能必须指出,在现实生活中,
水果
和苹果
的初始值设定项应该设置的属性数量是可变的,总共大约15个。我会将创建逻辑完全从类中拉出:
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, my_string):
color, kind = my_string.split()
my_class = globals().get(kind.capitalize(),Fruit)(color)
assert isinstance(my_class, Fruit),"Error Unknown Kind %s"%kind
return my_class
class Apple(Fruit):
def __init__(self,color):
self.tasty = True
Fruit.__init__(self,color)
def bite(self):
print "I bite into a tasty apple"
a = Fruit.fromstring("red apple")
print a
a.bite()
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
类都需要更新,本质上限制了扩展它的任何简单方法。如果您正在设计一个我想要的库,我不能重用水果,因为我不能添加香蕉、橘子或任何你没有的水果,而不改变你的代码,这与代码重用是对立的。我认为你需要评估基类代表什么
是否每个水果都需要一种颜色(您的observe
函数会建议它至少需要一个默认值,以便在调用时不会导致错误)?如果是这样,它应该是水果构造函数的一部分,并且应该是创建水果所必需的
从我的评论来看,我也对您的基类实例化子类型持怀疑态度。
Fruit
是否应该知道其所有子类型(例如,请参见答案)?Fruit是否应该提供构造函数?也许基类应该是一个bass类,应该有某种facxtory来稳定正确的水果类型,那么水果根本不需要知道子类。我只是认为调用fruit.fromstring()将是制作水果的一种很好的方法。不,Fruit不需要注意儿童。“我可能必须指出,在现实生活中,Fruit
和Apple
的初始值设定者应该设置的属性数量是可变的,总共大约15个。”-这是一种主要的代码气味。为什么要在初始化时设置15个属性?你能把你的问题扩展得更接近“现实生活”吗?我相信你在寻找一个工厂函数,它类似于fromstring
,只是你不会让它成为放射性香蕉的Fruit
+1的成员(我投票是因为逻辑分离,而不是香蕉)看起来您只是简单地将我的类方法移到了类之外:P我想知道为什么这比其他方法更可取。@squirrel我更新了代码,讨论了为什么将代码从Fruit类中删除。dm03514也是如此。@LegoStormtroopr阅读你的答案,我意识到我问这个问题有多么糟糕(我认为它几乎完美)。我忘了指出水果的数量是可变的,并不真正取决于苹果或香蕉。这意味着以您的方式(无疑是最好的方式)完成这项工作需要制作一个参数字典,以便Appale
的\uuuu init\uuuu
,后者必须决定哪些参数是他的,哪些属于Fruit的初始值设定项。但我想我没办法。谢谢,对我糟糕的提问技巧表示歉意:)每个水果都需要并将有一个颜色,输入字符串的某些部分将是统一的。乐高的想法本质上是方法#1,但它需要传递两次color
(实际上,传递的参数数量可变,最多可达10个),嗯,这只是一个评论还是一个问题的答案?也就是说,传递变量是一种方法?