Почему я получаю ошибку , принимает 2 позиционных аргумента, но 3 были даны, я буквально следовал всему, что делал мой учитель

#python

Вопрос:

Я новичок в ООП и мне трудно понять, что я делаю не так

 class Dog:  def __init__(self,name):  self.name = name  class pup(Dog):  def __init__(self, name):  super().__init__(pup, self) sammy = pup('sammy')  print(sammy.name)  

Комментарии:

1. Если это то, что сделал ваш учитель, то ваш учитель совершил ошибку. Вообще нет необходимости определять pup.__init__ , но если вы это сделаете, он должен позвонить super().__init__(name) .

Ответ №1:

Итак, идея наследования ООП заключается в том, что у вас есть подкласс ( Puppy ), который наследует свое «поведение» от суперкласса ( Dog ), т. е. все свойства, которыми обладает собака, щенок также выполняет по умолчанию.

Таким образом, вы почти всегда хотите инициализировать подкласс таким же образом, как инициализируется суперкласс, поскольку в нем задано множество экземпляров.

В вашем примере давайте дадим Dog вызываемый атрибут name и вызываемый метод bark

 class Dog:  def __init__(self,name):  self.name = name   def bark(self):  print("woof")  

затем мы можем создать экземпляр того, что отлично работает

 dog = Dog("sammy") print(dog.name) # "sammy" dog.bark() # "woof"  

Теперь мы хотим создать вызываемый подкласс Pub , который должен иметь тот же метод ( bark ) и атрибут ( name ), Dog что и . Давайте просто инициализируем его, ничего не делая

 class Pup(Dog):  def __init__(self,name):  pass  pup = Pup("sammy") pup.bark() # "woof" pup.name # AttributeError: 'pup' object has no attribute 'name'  

как вы можете видеть, у него нет имени, потому что мы перезаписали __init__ функцию из родительского ( Dog ), которая должна была установить этот атрибут. Из-за этого нам нужно вызвать родительскую __init__ функцию внутри нашей функции

 class Pup(Dog):  def __init__(self,name):  super().__init__(name) #call the Dogs __init__ function  pup = Pup('sammy') pup.bark() # "woof" print(pup.name) # "sammy"  

Это, конечно, игрушечный пример, и мы могли бы просто установить атрибут name, просто скопировав строки из Dog метода s __init__ в метод Pup s __init__ , но идея наследования состоит в том, чтобы избежать всей этой копипасты кода.

Когда вы создаете этот подкласс Pup с суперклассом Dog , вы (неудачно) говорите: «создайте класс Pup , вызванный копированием всего кода из Dog в Pup».

Комментарии:

1. Если вы вообще не определяете Pup.__init__ , то Dog.__init__ наследуется и будет вызываться с name аргументом в качестве аргумента. Это предпочтительнее, чем явно определять ненужную оболочку.

2. Хороший момент — это было просто для иллюстрации того, почему super().__init__ он был там и т. Д.

Ответ №2:

 class Dog:  def __init__(self,name):  self.name = name  class pup(Dog):  def __init__(self, name):  Dog.__init__(self, name) sammy = pup('sammy')  print(sammy.name)  

Ответ №3:

нет необходимости передавать self super().__init__() кому в строке 7.

Кроме того, я думаю, что вы должны реализовать это таким образом:

 class Dog:  def __init__(self,name):  self.name = name  class pup(Dog):  def __init__(self, name):  super().__init__(name) sammy = pup('sammy')  print(sammy.name)  

Комментарии:

1. Нет смысла определять pup.__init__ , все ли, что он делает, — это вызывает super().__init__ с теми же самыми аргументами.