【问题标题】:Python child instance property appears to be overridden by parent propertyPython 子实例属性似乎被父属性覆盖
【发布时间】:2019-07-04 14:29:20
【问题描述】:

我正在学习 Python 3 并编写概念性代码以帮助我理解。我在一个简单的类继承示例中遇到了一个问题,其中来自子类的实例变量似乎被父变量覆盖。

我已经以各种形式使用了以下代码,并出于此问题的目的对其进行了简化。当我在 Child 类中使用 self.name 来引用 Child 的 name 属性时,我无法弄清楚为什么 Child 对象自己的 __str__() 方法引用了 Parent 的 name 属性(它是好像self.name 被替换为super().name)。

class Parent():

    """ Parent class that will take a name or default to 'Default Parent'.
    """

    def __init__(self, name="Default Parent"):
        self.name = name

    def __str__(self):
        return f'Parent: I am {self.name}'

class Child(Parent):

    """ Child class inheriting from Parent class
    """

    def __init__(self, name="Default Child"):
        # setting self.name to the name passed in during Child instantiation
        self.name = name
        # not passing self.name so parents's self.name will be defaulted to "Default Parent"
        super().__init__() 

    def __str__(self):
        # self.name prints "Default Parent"
        # The property self.name in Child appears to be overridden.
        # Thought self.name here refers to the instant variable belonging to the instance of Child and not super().name.
        return f'Child: I am {self.name}'

我对此进行了如下测试:

p1 = Parent("Parent 1")
c1 = Child("Child 1")
print(p1)
print(c1)

我期待这些结果回来:

Parent: I am Parent 1
Child: I am Child 1

相反,我得到了这些:

Parent: I am Parent 1
Child: I am Default Parent

【问题讨论】:

    标签: python class inheritance instance


    【解决方案1】:

    Child 中设置self.name 后,您正在调用super().__init__()。这是覆盖属性。相反,将 name 参数传递给父 init。

    class Child(Parent):
    
        """ Child class inheriting from Parent class
        """
    
        def __init__(self, name="Default Child"):
            super().__init__(name=name) 
    

    【讨论】:

    • 嗨。谢谢你。我意识到将名称显式传递给父级会设置父级名称。这是否意味着子类属性“名称”不能与父属性“名称”隔离存在?或者换一种说法,如果 name 是 Parent 中的 method,并且 name 也是 Child 中的 method,则调用 child 的 name 方法将覆盖 parent 的 name 方法 - 它永远不会在 Child 中调用 self.name() 会调用父级的 name 方法。那么为什么属性/变量会有所不同呢?
    • 您创建了两个属性“名称”:一个在父级中,另一个在子级中。但是,在您的情况下,“名称”可能存在于 Parent 中。 Child 中的另一个“名称”是不必要的冗余,并且无论如何都会被 super().__init__(name=name) 覆盖。如果您真的想在 Child 中使用单独的“名称”,请不要调用 super().__init__()。
    • 这很合理,我现在可以看到设计中的冗余性质。我还在学习 Python 的做事方式,你的所有回答都帮助我更进一步。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-01-19
    • 2014-09-19
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2011-09-29
    相关资源
    最近更新 更多