#python #python-3.x #class #inheritance
#python #python-3.x #класс #наследование
Вопрос:
Я не уверен, задавались ли эти вопросы, поскольку я не вижу никаких подобных проблем.
Ниже приведены мои проблемы:
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
Комментарии:
1. Ваши ожидания странные / плохие.
Child()
был создан без какого-либо имени и возраста, почему он должен повторно использовать данные из какого-либо другого не связанного экземпляра?2. Вы не передали имя или возраст при создании экземпляра
Child
, поэтому, естественно, у этого экземпляра нет имени или возраста.3. Предположим, у вас есть два объекта
p1 = Parent(name="Derek", age=22)
иp2 = Parent(name="Donna", age=21)
. Какие значения вы ожидаетеChild()
унаследовать? Наследование применяется к поиску имен в иерархии классов , а не к отношениям между отдельными экземплярами этих классов.4. Вам следует пока избегать использования
**kwargs
. Кажется, это затрудняет ваше понимание того, что происходит.5. Я не могу сказать наверняка, но мне кажется, что вы путаете классы и экземпляры классов. это очень разные вещи.
Ответ №1:
Наследование, грубо говоря, имеет дело с концепциями уровня класса. Рассмотрим этот родительский класс:
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; наследование не задействовано. (Наследование участвует в настройке атрибутов name
и age
, поскольку вы вызываете 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])
]
Комментарии:
1. Спасибо за ваш ответ, я думаю, что основной смысл вашего ответа здесь — передать родительский класс дочернему классу. c = Дочерний класс(«Didi», 9, p)
2. Я все еще должен придерживаться ** kwargs, поскольку моя организация использует его. Однако я делаю следующее:
c = Child(parent_class = p)
а затем обрабатываю это с помощьюp = kwargs.get(parent_class,None)
, а затем продолжаю сself.parent_name = p.name
3.
parent
, неparent_class
.p
является экземпляромParent
, а не самим классом. Серьезно, убедитесь, что кто-то в вашей организации проводит проверку кода того, что вы пишете, потому что вы, похоже, недостаточно хорошо понимаете основы, чтобы писать что-либо самостоятельно.4. opps .. понял. Да, есть старший … но он сейчас в отъезде. Итак, ищу помощь здесь