python - 如果子类由构造逻辑确定,那么分离类及其父类逻辑的最pythonic和优雅的方法是什么?

标签 python class inheritance

我想从"red apple" 等字符串构造类。这将创建类 Apple 的实例,它是 Fruit 的子类。问题是,color 属性应该属于 Fruit,而不是 Apple。因此,在我看来,创建对象的自然方式是:

  1. 解析字符串
  2. 创建Fruit(color="red")
  3. 创建 Apple()
  4. 以某种方式使其成为一个实体

到目前为止,我有 3 个选择:

  1. 一切都变成参数

    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")
    
  2. 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")
    
  3. 最直接的方法:替换__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__ 听起来像是使用高级工具来完成一项平凡的任务。是否有更好的方法来实现目标,或者我最好使用其中一种方法?

更新:我可能必须指出,在现实生活中,FruitApple 的初始化器应该设置的属性数量是变量,总共约 15 个。

最佳答案

我会将创建逻辑完全从类中拉出来:

  1. 解析字符串
  2. 确定要创建的对象
  3. 创建对象

所以使用下面的代码:

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/

相关文章:

c++ - 关于c++继承的困惑

c++ - 在 C++ 中,如何在基函数中访问派生类的成员? (这甚至是正确的做法吗?)

c++ - 虚函数和性能 C++

python - Ansible playbook 在所有 Ubuntu 服务器上均失败

c++ - 类实例的 std::thread

java - 如何在 eclipse、tomcat 和 stripes 下将 .java 文件更改传播为 .class

c# - 转到实现的方法而不是接口(interface)

python - Tweepy API 调用不起作用

python - 如何将列表对象中存在的列名添加到表中

python - 将 Pandas 中的列索引重置为 0,1,2,3 ...?