首页 > python > 子类继承父类self.variable

子类继承父类self.variable (Child class inherit Parent class self.variable)

问题

我不确定是否已经问过这个问题,因为我看不到任何类似的问题。

以下是我的问题:

class Parent(object):
    def __init__(self,**kwargs):
        self.name = kwargs.get('name',None)
        self.age = kwargs.get('age',None)
        self.year = '1995'
        print(self.name,self.age,self.year)

class Child(Parent):
    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        self.parent_name = self.name
        self.parent_age = self.age
        self.parent_year = self.year
        print("Parent Details: ",self.parent_name,self.parent_age,self.parent_year)

>>> res = Parent(name='Derek',age=22)
Derek 22 1994
>>> res2 = Child()
None None 1994

我的问题是,为什么子类返回None?我已经使用super()继承父init类。以下是我的期望,我该如何实现?

>>> res = Parent(name='Derek',age=22)
Derek 22 1994
>>> res2 = Child()
Parent Details: Derek 22 1994

解决方法

粗略地说,继承涉及类级概念。考虑这个父类:

class Parent(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.year = '1995'

    def eat(self, food):
        print("I ate {}".format(food))

现在考虑这个子类:

class Child(Parent):
    def __init__(self, name, age, p):
        super().__init__(name, age)
        self.parent_name = p.name
        self.parent_age = p.age
        self.parent_year = p.year
        # Or, since you can already access the name, age, and year of
        # an instance of Parent, just save the instance directly:
        self.parent = p

然后你可以写

p = Parent("Derek", 22)
c = Child("Didi", 9, p)

现在c.parent_name == "Derek"c.parent_age == 22,但是c.name == "Didi"c.age == 9。你明确告诉 Child Didi的父母是谁; 继承不涉及。(继承参与制定nameage属性,因为你打电话super().__init__,但是这是一种奇怪的类层次,Child是一个子类的Parent,但并没有真正模拟现实世界的非常好:不是所有的孩子都是父母的。)

继承进来的地方是eat方法。有没有Child.eat方法,所以当你打电话c.eat("apple"),什么情况是Parent.eat被称为一个Child实例作为其第一个参数。

>>> p.eat("apple")
"I ate apple"
>>> c.eat("apple")
"I ate apple"

继承应该用来模拟“is-a”关系; 如果B继承自A,那么对于所有意图和目的,实例B应该可以在任何实例可用的地方A使用。你在这里的使用违反了这一点; a Child 父,但不一定是父本身,所以Child不应继承Parent。更合理的建模只涉及一个类:

class Person:
    def __init__(self, name, age, parents=None):
        self.name = name
        self.age = age
        self.parents = parents

# We've lost the genealogical records, and don't know who
# Bob and Alice's parents were.
first_man = Person("Alice", 25)
first_woman = Person("Bob", 25)
children = [
    Person("Charlie", 15, [first_man, first_woman]),
    Person("Derek", 13, [first_man, first_woman])
]

问题

I am not sure if this questions has been asked as I can't see any similar issues.

Below are my issues:

class Parent(object):
    def __init__(self,**kwargs):
        self.name = kwargs.get('name',None)
        self.age = kwargs.get('age',None)
        self.year = '1995'
        print(self.name,self.age,self.year)

class Child(Parent):
    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        self.parent_name = self.name
        self.parent_age = self.age
        self.parent_year = self.year
        print("Parent Details: ",self.parent_name,self.parent_age,self.parent_year)

>>> res = Parent(name='Derek',age=22)
Derek 22 1994
>>> res2 = Child()
None None 1994

My question is, why does the child class return None? I have already used super() to inherit the parent init class. Below is my expectation and how can I achieve that?

>>> res = Parent(name='Derek',age=22)
Derek 22 1994
>>> res2 = Child()
Parent Details: Derek 22 1994

解决方法

Inheritance, roughly speaking, deals with class-level concepts. Consider this parent class:

class Parent(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.year = '1995'

    def eat(self, food):
        print("I ate {}".format(food))

Now consider this child class:

class Child(Parent):
    def __init__(self, name, age, p):
        super().__init__(name, age)
        self.parent_name = p.name
        self.parent_age = p.age
        self.parent_year = p.year
        # Or, since you can already access the name, age, and year of
        # an instance of Parent, just save the instance directly:
        self.parent = p

Then you could write

p = Parent("Derek", 22)
c = Child("Didi", 9, p)

Now c.parent_name == "Derek" and c.parent_age == 22, but c.name == "Didi" and c.age == 9. You explicitly told Child who the parent of Didi was; inheritance is not involved. (Inheritance is involved in setting the name and age attributes, since you call super().__init__, but this is kind of a weird class hierarchy. Child is a child class of Parent, but that doesn't really model the real world very well: not all children are parents.)

Where inheritance comes in is with the eat method. There is no Child.eat method, so when you call c.eat("apple"), what happens is Parent.eat gets called with a Child instance as its first argument.

>>> p.eat("apple")
"I ate apple"
>>> c.eat("apple")
"I ate apple"

Inheritance should be used to model "is-a" relationships; if B inherits from A, then for all intents and purposes an instance of B should be usable anywhere an instance of A is usable. Your use here violates that; a Child has a parent, but is not necessarily a parent itself, and so Child should not inherit from Parent. A more sane modeling would involve just one class:

class Person:
    def __init__(self, name, age, parents=None):
        self.name = name
        self.age = age
        self.parents = parents

# We've lost the genealogical records, and don't know who
# Bob and Alice's parents were.
first_man = Person("Alice", 25)
first_woman = Person("Bob", 25)
children = [
    Person("Charlie", 15, [first_man, first_woman]),
    Person("Derek", 13, [first_man, first_woman])
]
相似信息