#python #class #object #oop #inheritance
Вопрос:
Я начинаю свое путешествие в ООП, пытаясь изучить наследование. Я видел этот код в онлайн-викторине по этой теме и надеялся, что кто-нибудь сможет мне его объяснить, так как для меня в этом мало смысла.
class A(object) : def __init__(self, x) : self._x = 2 * x def m1(self, x) : return self.m2(x) 2 def m2(self, x) : return x - 1 class B(A) : def m2(self, y) : self._y = y return self._x self._y
Для следующего, если бы я сказал a = A(1), какова была бы ожидаемая отдача? Инициализация умножает 1 на 2, так что теперь экземпляр x имеет значение 2. Что происходит с методом m1? он получает этот экземпляр X, но в возврате он ссылается на m2? итак, получается, что x=2 сначала передается в m2, а затем возврат 1 передается в m1? что добавляет к нему 2?
Что касается класса B, я вижу, что он изменяет унаследованный метод m2 из класса A, но значение x, добавляемое к y, является ли это унаследованным значением x из класса A?
Извините за бесконечные вопросы, но я только начинаю, и мне кажется, что это трудно осознать.
Комментарии:
1. Вот вопрос и дополнительные утверждения, которые я должен был применить. a = A(1) b = B(2) c = C(1, 1) d = D(2, 1) Что возвращает a.m1(2)?
2. Что такое
C
иD
?3. Принимая x за 2 в m1, это приводит к правильному ответу 3. Но мне интересно, какое отношение a=A(1), как было указано ранее, имеет к этому вопрос?
4. @Codeman Я мог бы добавить их, если это необходимо, но я чувствовал, что понимание первого шага позволит мне завершить все остальное самостоятельно, что было бы истинным обучением, в которое я верю.
5. Очень хорошо. Не могли бы вы подробнее остановиться на «ожидаемой прибыли»? Вы говорите о m1 или m2?
Ответ №1:
Самый простой способ выяснить, что делает код, — это запустить его.
gt;gt;gt; a = A(1) gt;gt;gt; a.m1(10) 11
Важная вещь, которую следует отметить здесь (что, судя по вашему вопросу, звучало так, как будто вы можете быть сбиты с толку), заключается в том, что значение x
, к которому вы переходите A.__init__
, не используется A.m1
! Поэтому A.m1(x)
просто возвращает x 1
независимо от того, как вы инициализировали A
экземпляр.
gt;gt;gt; a = A(1000) gt;gt;gt; a.m1(1) 2 gt;gt;gt; a.m1(10) 11 gt;gt;gt; a.m1(100) 101
Хорошо, а что, если мы сделаем B
то же самое?
gt;gt;gt; b = B(1) gt;gt;gt; b.m1(10) 14
Теперь все по-другому, потому B.m2
что отличается от A.m2
. Мы можем просто запустить их самостоятельно, чтобы посмотреть:
gt;gt;gt; a.m2(10) 9 gt;gt;gt; b.m2(10) 12
a.m2(10)
равно 9, потому a.m2(x)
что всегда просто x - 1
, независимо от того, что a._x
есть.
Но b.m2(10)
возвращается b._x 10
, что в данном случае равно 12-и поэтому b.m1(10)
возвращает это плюс 2. Результаты будут другими, если мы изменим то, что b._x
есть, инициализировав наше B
значение другим значением:
gt;gt;gt; b = B(2) gt;gt;gt; b.m2(10) 14 gt;gt;gt; b.m1(10) 16
Комментарии:
1. Ах, в этом есть большой смысл! Большое вам спасибо за то, что нашли время помочь мне. Сейчас я попробую все остальное!
2. Каково значение y, введенное в m2 класса B? и как получилось, что a.m2(x) не зависит от a._x, где как b.m2 зависит? Редактировать: Я понимаю, как это зависит, так как он добавляет self._x к self._y, поэтому он использует начальный экземпляр x с новым экземпляром y, верно?
3. @AgentiDiogenes Значение y не зависит от того, что вы передаете в функции, но
B(x).m2(y)
зависит не толькоy
от того, с какого момента вы используете функциюself._x
fromsuper().__init()
. ДляA
, вы не используетеself._x
, поэтому m1/m2 называется какA(x).m1(y)
и зависит только отy
.4. Я отмечу, что установка атрибута экземпляра в случайном методе является плохой практикой и делает понимание наследования излишне запутанным-если этот код является частью онлайн-курса, у меня возникают сомнения в том, насколько хорош курс.
Ответ №2:
Вы всегда можете отследить, что происходит:
... class B(A) : def m2(self, y) : self._y = y return self._x self._y
class B
тогда выглядит так Bx
, как m2
переопределено:
class Bx: def __init__(self, x) : self._x = 2 * x def m1(self, x) : return self.m2(x) 2 def m2(self, y) : self._y = y return self._x self._y
Так вот как class B
это выглядит, когда он унаследовал
Комментарии:
1. Ах ,так вот как это действительно выглядит после наследования методов от А. Имеет смысл, спасибо!
Ответ №3:
Я постараюсь ответить на ваши вопросы по порядку:
- Если бы вы сказали
a = A(1)
,__init__
установил бы переменную self._x в2
. Это не изменится, так как после этого вы никогда не редактируетеself._x
переменную.- Функции
m1
иm2
могут возвращать все, что угодно, на основеx
того, что вы передаете. Ты это имел в видуself._x
? И да,m2
выполнял бы , когда вы звонитеm1
,m1
ибо любой номерx
просто возвращалсяx 1
бы .
- Функции
a = A(1)
это просто создание экземпляра классаA
, методы будут работать только с justA(x).m1(y)
, тогда как если бы вы включилиa = A(1)
, вы бы выполнилиa.m1(y)
.- Создание экземпляра класса
B
с любым числом (B(x)
) запускает__init__()
функциюA
(super().init(args)
) сx
переданным (попробуйте запустить ее самостоятельно с помощью чего-то подобногоb = B(2); print(b._x)
!). Таким образом,self._x
2 * x
получается, что вы прошли за Б! - Вы перезаписали метод
m2()
в классеB
, поэтомуm2()
A
в нем не используется метод fromB
.
Если у вас есть какие-либо другие вопросы, прокомментируйте, и я попытаюсь ответить на них!