<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 22:28:16 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="j0HvbTIECGCzohTh45c39HeALuh9C_mgxM8gkSa-AYBgkCRawHqlAAXhMHnvmMeDt4kDQnU8BwJ5L7rFdLnm7g";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Наследование | Python: Введение в ООП</title>
<meta name="description" content="Наследование / Python: Введение в ООП: Познакомимся с механизмом наследования классов в Python. Узнаем, как наследование помогает повторно использовать объектный код">
<link rel="canonical" href="https://ru.hexlet.io/courses/python-oop-basics/lessons/inheritance/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Наследование">
<meta property="og:title" content="Python: Введение в ООП">
<meta property="og:description" content="Наследование / Python: Введение в ООП: Познакомимся с механизмом наследования классов в Python. Узнаем, как наследование помогает повторно использовать объектный код">
<meta property="og:url" content="https://ru.hexlet.io/courses/python-oop-basics/lessons/inheritance/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="rIBv_PW-yDIeMTzEdG0KCLsVnuZPrwl8DP5tja1NsjJDUaTLB8BlUqhyGFx4Yvp_exyzTEeY996xHvfZ_0pVXA" />
<script src="/vite/assets/inertia-DfXos102.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-cb8xch9l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczMSwicHVyIjoiYmxvYl9pZCJ9fQ==--f5df4883f3f678321cb4fa96e9ce657bd5ee1adf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc0OSwicHVyIjoiYmxvYl9pZCJ9fQ==--846349326718432328cf5c0677091aca67f80af3/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Developer%20activity-amico%20(1).png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyMCwicHVyIjoiYmxvYl9pZCJ9fQ==--71cd9d863b21d7bfbd927cf623a7a2baaf4530ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-cuate.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIyMiwicHVyIjoiYmxvYl9pZCJ9fQ==--0e824331c2dcddbe1fa1aaa4188500e364c8c38c/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-bro.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T22:28:16.398Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"-qrNXIEmAOabAG9b94VKgiaAPjKu-TRgZtz-hBNmZ0cVewZrc1ithi1DS8P7irr15okTmKbOysLbPGTQQWGAKQ","topics":[{"id":41755,"title":"```\nclass LimitedCounter(Counter):\n def __init__(self, limit):\n super().__init__()\n self.limit = limit\n\n def inc(self, amount=1):\n print(super().__dict__)\n print(self.__dict__)\n print(self.value)\n print(super().value)\n\n{'value': 0, 'limit': 10}\n{'value': 0, 'limit': 10}\n0\n---------------------------------------------------------------------------\nAttributeError Traceback (most recent call last)\n in \n 31 \n 32 l = LimitedCounter(10)\n---> 33 l.inc(12)\n\n in inc(self, amount)\n 23 def inc(self, amount=1):\n 24 print(super().__dict__)\n---> 25 print(super().value)\n 26 if super().__dict__['value1'] + amount > self.limit:\n 27 super().__dict__['value'] = self.limit\n\nAttributeError: 'super' object has no attribute 'value'\n```\n\nДандер dict у super() показывает {'value': 0, 'limit': 10} То есть у super() есть атрибут value и почему то и limit..\nНо обратиться к super().value не дает, пишет AttributeError.\n\nОткуда у суперкласса появился limit и не работает super().value?\n","plain_title":"class LimitedCounter(Counter): def __init__(self, limit): super().__init__() self.limit = limit def inc(self, amount=1): print(super().__dict__) print(self.__dict__) print(self.value) print(super().value) {'value': 0, 'limit': 10} {'value': 0, 'limit': 10} 0 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) in 31 32 l = LimitedCounter(10) ---> 33 l.inc(12) in inc(self, amount) 23 def inc(self, amount=1): 24 print(super().__dict__) ---> 25 print(super().value) 26 if super().__dict__['value1'] + amount > self.limit: 27 super().__dict__['value'] = self.limit AttributeError: 'super' object has no attribute 'value' Дандер dict у super() показывает {'value': 0, 'limit': 10} То есть у super() есть атрибут value и почему то и limit.. Но обратиться к super().value не дает, пишет AttributeError. Откуда у суперкласса появился limit и не работает super().value? ","creator":{"public_name":"Elena Ilchenko","id":269595,"is_tutor":false},"comments":[{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":91003,"body":"Сначала разберёмся с видимостью limit.\n\n`super()` не затрагивает `__dict__` - фактическое состояние объекта одно и то же, даже если вы меняете \"точку зрения\" с помощью вызова super. Вы можете даже вывести `id(self.__dict__)` и `id(super().__dict__)` и увидите, что это один и тот же объект.\n\nТеперь разберёмся с \"value\".\n\n`super()` не позволяет получить доступ к *атрибутам экземпляра*, он работает только атрибутами классов (методы тоже являются таковыми).\n\nДело в том, что объект, который возвращает вызов super, получает из иерархии имя класса-предка, а затем ждёт, когда вы обратитесь к атрибуту этого класса. Если атрибутом окажется метод, то он будет связан (bound) на время вызова с текущим экземпляром. Поэтому работают вызовы вроде `super().__init__()`. Атрибуты класса-предка, не являющиеся методами, возвращаются \"как есть\", поэтому работает пример из урока.\n\nС атрибутами же экземпляра super в принципе не может работать. Ведь текущий экземпляр не содержит в себе экземпляров предков. Поэтому не могут существовать атрибуты экземпляров предков, к которым можно было бы обратиться.\n\n---\n\nЯ несколько двусмысленно описал в уроке то, что super работает с атрибутами классов. Так что спасибо, что обратили на это моё внимание - я уточню этот момент.","topic_id":41755}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":50427,"title":"Доброе утро. Хотел бы прояснить один вопрос чтобы закрепить материал. Функции всегда работают со своим пространством имен если им явно не определить global. Для того чтобы метод класса (экземпляра) inc() как код работал с данными класса (атрибутами) на примере задачи про Counter, ему нужно 'видеть' value. Но мы не задаём в методе global. Но метод видит и работает с value. Получается их сообщение между собой идёт не напрямую через пространство имен, а через дандер __dict__? Или же класс делает пространство имен единым для всех 'отступов' (функций), а дандер __dict__ тут не причем? Подскажите пожалуйста ","plain_title":"Доброе утро. Хотел бы прояснить один вопрос чтобы закрепить материал. Функции всегда работают со своим пространством имен если им явно не определить global. Для того чтобы метод класса (экземпляра) inc() как код работал с данными класса (атрибутами) на примере задачи про Counter, ему нужно 'видеть' value. Но мы не задаём в методе global. Но метод видит и работает с value. Получается их сообщение между собой идёт не напрямую через пространство имен, а через dict? Или же класс делает пространство имен единым для всех 'отступов' (функций), а dict тут не причем? Подскажите пожалуйста ","creator":{"public_name":"Егор","id":318046,"is_tutor":false},"comments":[{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":108093,"body":"Все функции, объявляемые в пределах \"оступа класса\", получают ссылку на экземпляр в первом параметре (`self`). Именно через этот параметр и происходит взаимодействие с состоянием класса и экземпляра.\n\nТо, что код класса выглядит как обычный блок, не должно вводить в заблуждение - это не \"последовательность действий в рамках пространства имён\" в прямом смысле. И объявления, сделанные в рамках тела класса, **не видят** друг друга.","topic_id":50427},{"creator":{"public_name":"Егор","id":318046,"is_tutor":false},"id":108094,"body":"Спасибо","topic_id":50427},{"creator":{"public_name":"Егор","id":318046,"is_tutor":false},"id":108095,"body":"**Aleksei Pirogov**, Спасибо","topic_id":50427}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":47231,"title":"Добрый \nМожете дать пояснение по моему решению есть ли в нем подводный камни https://ru.hexlet.io/code_reviews/313403\nСпасибо ","plain_title":"Добрый Можете дать пояснение по моему решению есть ли в нем подводный камни https://ru.hexlet.io/code_reviews/313403 Спасибо ","creator":{"public_name":"Евгений Александрович","id":281154,"is_tutor":false},"comments":[{"creator":{"public_name":"Виктор Меркушов","id":292041,"is_tutor":false},"id":102107,"body":"**Евгений Александрович**, как ученик, отмечу:\n- Вы отнаследовали класс LimitedCounter от Counter, но не используете преимущества наследование в коде.\n- def limit через @property и его использование (self.limit) очень сильно запутывает тех, кто будет этот код читать\n","topic_id":47231},{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":101927,"body":"Евгений, доброе утро! Вижу, что вы активно занимаетесь на Хекслете. Менторы помогают пользователям в поиске решения, отладке программы, работе с документацией и т.д. Ревью решений менторы не делают. Эти правила вынесены в отдельный раздел справки - [На какие вопросы отвечают менторы](https://help.hexlet.io/article/39-mentors).\n\nЕсли у вас есть конкретные вопросы по решению - задавайте. ","topic_id":47231}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":46300,"title":"Для чего мы вызываем инициализацию класса предка, в потомке? \n`super().__init__()`","plain_title":"Для чего мы вызываем инициализацию класса предка, в потомке? super().__init__() ","creator":{"public_name":"Костя Парфёнов","id":123307,"is_tutor":false},"comments":[{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":99998,"body":"Если предок выполняет какие-то действия в процессе инициализации, скажем, заполняет какие-то поля, нужные для работы методов, то для того, чтобы не переопределённые методы потомка работали корректно, нужно при его инициализации вызвать инициализатор предка.\n\nЕсли вы абсолютно уверены в том, что не забудете в потомке инициализировать всё, что может потребоваться предку, то `__init__` предка можете не вызывать. Но если код предка поменяется, то что-то может сломаться :)","topic_id":46300}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":50724,"title":"Кирилл Мокевнин много говорит про критику ООП. Где можно найти видео\\статьи на эту тему? Подскажите пожалуйста. Буду благодарен. ","plain_title":"Кирилл Мокевнин много говорит про критику ООП. Где можно найти видео\\статьи на эту тему? Подскажите пожалуйста. Буду благодарен. ","creator":{"public_name":"","id":168,"is_tutor":false},"comments":[{"creator":{"public_name":"Сергей К.","id":5174,"is_tutor":false},"id":108538,"body":"Вот [ссылка](https://twitter.com/mokevnin/status/1341804176544829444) на 2 треда по ООП в твиттере.","topic_id":50724},{"creator":{"public_name":"","id":168,"is_tutor":false},"id":108549,"body":"спасибо","topic_id":50724}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":77332,"title":"Решение с новым свойством - это просто в методических целях или есть у такого подхода какое-нибудь преимущество перед простым [переписыванием метода inc](https://ru.hexlet.io/code_reviews/758597)?\n\nКстати, есть ли способ reuse родительский inc, используя super? Чтобы заново не задавать нижний предел?\n\n","plain_title":"Решение с новым свойством - это просто в методических целях или есть у такого подхода какое-нибудь преимущество перед простым переписыванием метода inc (https://ru.hexlet.io/code_reviews/758597)? Кстати, есть ли способ reuse родительский inc, используя super? Чтобы заново не задавать нижний предел? ","creator":{"public_name":"Виталий","id":419171,"is_tutor":false},"comments":[{"creator":{"public_name":"Ivan Mamtsev","id":294764,"is_tutor":true},"id":160497,"body":"Добрый день, в комментарии есть ответ:\n\n\"Если вы просто унаследуете Counter и переопределите метод inc, то такое решение тоже будет правильным. Данное решение нарочно демонстрирует альтернативный подход :)\"\n\n> Кстати, есть ли способ reuse родительский inc, используя super? Чтобы заново не задавать нижний предел?\n\nМожно как-нибудь так\n\n```python\nsuper().inc(amount=amount)\nself.value = min(self.value, self.limit)\n```","topic_id":77332}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":63698,"title":"Теории к сожалению не хватает для выполнения упражнения, пришлось дополнительно читать литературу, что бы осознать, что при инициализации необходимо вызывать инициализатор супер класса.\n\nНу и максимально переиспользовать методы, особо тоже мысле-топлива не хватило\nhttps://ru.hexlet.io/code_reviews/537437","plain_title":"Теории к сожалению не хватает для выполнения упражнения, пришлось дополнительно читать литературу, что бы осознать, что при инициализации необходимо вызывать инициализатор супер класса. Ну и максимально переиспользовать методы, особо тоже мысле-топлива не хватило https://ru.hexlet.io/code_reviews/537437 ","creator":{"public_name":"Александр Новиков","id":169561,"is_tutor":false},"comments":[{"creator":{"public_name":"Nikolai Gagarinov","id":104929,"is_tutor":true},"id":134207,"body":"Александр, добрый день.\n\nСпасибо за обратную связь. Поставил создал тикет для улучшения теории. После того как поправим - напишем об этом =)\nПомните, что вы можете задавать вопросы по ходу обучения ещё и в нашем [слаке](https://slack-ru.hexlet.io/) в канале `#python`","topic_id":63698}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":39221,"title":"Зачем в решении учителя дополнительный атрибут `_actual_value`?\nПочему нельзя работать с self.value напрямую?\nКакие преимущества дает отдельный атрибут?","plain_title":"Зачем в решении учителя дополнительный атрибут _actual_value? Почему нельзя работать с self.value напрямую? Какие преимущества дает отдельный атрибут? ","creator":{"public_name":"Victor Shabratsky","id":110214,"is_tutor":false},"comments":[{"creator":{"public_name":"Victor Shabratsky","id":110214,"is_tutor":false},"id":85859,"body":"На всякий случай, [ссылка](https://ru.hexlet.io/code_reviews/226446) на ревью.","topic_id":39221},{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":85867,"body":"Что же касается подчеркивания, то это часть соглашения по именованию сущностей \"для внутреннего пользования\" (как ещё говорят, *приватных/private*): атрибуты, методы, переменные, функции считаются таковыми, если их имя начинается с одиночного символа подчёркивания. Я про это напишу отдельный урок как-нибудь :)","topic_id":39221},{"creator":{"public_name":"Victor Shabratsky","id":110214,"is_tutor":false},"id":85872,"body":"Спасибо.","topic_id":39221},{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":85869,"body":"По ревью: вы переопределяете метод `inc`, но аргумент `amount` объявляете и передаёте явно. Хотя в вашем коде аргумент не используется. Если в предке изменится имя аргумента, его значение по умолчанию, добавится новый аргумент - в любом случае ваш класс перестанет быть \"равноценной заменой\" или вообще перестанет работать!\n\nЕсли вы никак не используете аргументы в методе потомка, а вместо этого просто передаёте всё, что есть, методу предка - используйте `*args` и `**kwargs`. В этом случае изменение сигнатуры метода предка ничего не сломает.","topic_id":39221},{"creator":{"public_name":"Victor Shabratsky","id":110214,"is_tutor":false},"id":85858,"body":"Зачем вообще делать из value свойство, когда уже есть такой атрибут? Само решение мне понятно. Мне не понятно зачем усложнять, делать геттер, сеттер, водить ещё одни атрибут. Дает ли такой способ какие-либо преимущества? Или просто для демонстрации одного из путей решения?\n\nИ еще вопрос. Почему наименование атрибута `_actual_value` начинается с нижнего подчеркивания? Это какое-то соглашение?","topic_id":39221},{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":85866,"body":"**Victor Shabratsky**, я специально написал, что решить задачу можно по-разному. Ваше решение - правильное и хорошее. Но не единственное :)\n\nПреимущество моего решения заключается в том, что вы можете изменять значение счётчика через присваивание значения атрибуту `value` и лимит всё ещё будет действовать:\n\n```python\n>>> lc = LimitedCounter(10) \n>>> lc.value \n0\n>>> lc.value += 50 \n>>> lc.value \n10\n```\n\nP.S. У меня в решении есть баг: счётчик можно увести в отрицательные числа. Поправлю :)","topic_id":39221},{"creator":{"public_name":"Aleksei Pirogov","id":72206,"is_tutor":true},"id":85855,"body":"`value` в учительском решении, это свойство. А свойству нужно некое поле, чтобы хранить значение.","topic_id":39221}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":49048,"title":"Добрый день! Первый раз за прохождение курсов встретил в выводе ошибку INTERNALERROR.\nВот ссылка на ревью: https://ru.hexlet.io/code_reviews/335617\nНа локальном компьютере тесты проходит, ошибок не выдаёт.\nТекст ошибки (первые строки):\n```\nINTERNALERROR> Traceback (most recent call last):\nINTERNALERROR> File \"/usr/lib/python3.8/shutil.py\", line 670, in _rmtree_safe_fd\nINTERNALERROR> os.unlink(entry.name, dir_fd=topfd)\nINTERNALERROR> PermissionError: [Errno 13] Permission denied:\n 'nodeids'\n```\n","plain_title":"Добрый день! Первый раз за прохождение курсов встретил в выводе ошибку INTERNALERROR: INTERNALERROR> Traceback (most recent call last): INTERNALERROR> File \"/usr/lib/python3.8/shutil.py\", line 670, in _rmtree_safe_fd INTERNALERROR> os.unlink(entry.name, dir_fd=topfd) INTERNALERROR> PermissionError: [Errno 13] Permission denied: 'nodeids' Вот ссылка на ревью: https://ru.hexlet.io/code_reviews/335617 На локальном компьютере тесты проходит, ошибок не выдаёт. ","creator":{"public_name":"Edward","id":310692,"is_tutor":false},"comments":[{"creator":{"public_name":"Edward","id":310692,"is_tutor":false},"id":105224,"body":"Спасибо!","topic_id":49048},{"creator":{"public_name":"Александр-C Вагин","id":6409,"is_tutor":false},"id":105221,"body":"Здравствуйте. Проблему исправил, нажмите Сброс в практике.","topic_id":49048},{"creator":{"public_name":"","id":321864,"is_tutor":false},"id":105219,"body":"потверждаю, та же ошибка","topic_id":49048}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}},{"id":84387,"title":"Подскажите пожалуйста, в чем моя ошибка?\nНа локальной машине, в VS code все успешно интерпретируется.... \nНе могу понять в чем причина\nhttps://ru.hexlet.io/code_reviews/919425","plain_title":"Подскажите пожалуйста, в чем моя ошибка? На локальной машине, в VS code все успешно интерпретируется.... Не могу понять в чем причина https://ru.hexlet.io/code_reviews/919425 ","creator":{"public_name":"Anton Nikolaev","id":589050,"is_tutor":false},"comments":[{"creator":{"public_name":"Aleksandr Litvinov","id":117182,"is_tutor":true},"id":170873,"body":"Посмотрите, результаты тестов показывают вам такую ошибку:\n\n```\n counter.inc()\n counter.inc(7)\n> assert counter.value == 8\nE assert 2 == 8\n```\n\nТам где функция должна увеличить счётчик на 7, она увеличивает на 1.","topic_id":84387}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Наследование","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":1112,"slug":"python_oop_basics_inheritance_exercise","name":null,"state":"active","kind":"exercise","language":"python","locale":"ru","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"## src/solution.py\n\nВам дан класс `Counter`, реализующий счетчик с инкрементом и декрементом. Вам нужно реализовать класс-потомок `LimitedCounter`, который будет отличаться от `Counter` тем, что при инициализации будет принимать в качестве аргумента лимит — максимальное возможное значение счетчика.\n\nТребования к классу `LimitedCounter`:\n\n- Класс должен максимально использовать методы предка, если таковые переопределяет\n- Минимальное значение счетчика `Counter` — 0, должно оставаться таковым и для `LimitedCounter`\n\n```python\ncounter = LimitedCounter(limit=10)\ncounter.inc()\ncounter.inc(7)\ncounter.value # 8\ncounter.dec(10)\ncounter.value # 0\ncounter.inc(7)\ncounter.inc(7)\ncounter.value # 10\n```\n\n### Подсказки\n\n- Задание можно решить разными способами. Нет единственного верного решения. Так что творите!\n","prepared_readme":"## src/solution.py\n\nВам дан класс `Counter`, реализующий счетчик с инкрементом и декрементом. Вам нужно реализовать класс-потомок `LimitedCounter`, который будет отличаться от `Counter` тем, что при инициализации будет принимать в качестве аргумента лимит — максимальное возможное значение счетчика.\n\nТребования к классу `LimitedCounter`:\n\n- Класс должен максимально использовать методы предка, если таковые переопределяет\n- Минимальное значение счетчика `Counter` — 0, должно оставаться таковым и для `LimitedCounter`\n\n```python\ncounter = LimitedCounter(limit=10)\ncounter.inc()\ncounter.inc(7)\ncounter.value # 8\ncounter.dec(10)\ncounter.value # 0\ncounter.inc(7)\ncounter.inc(7)\ncounter.value # 10\n```\n\n### Подсказки\n\n- Задание можно решить разными способами. Нет единственного верного решения. Так что творите!\n","has_solution":true,"entity_name":"Наследование"},"units":[{"id":3701,"name":"theory","url":"/courses/python-oop-basics/lessons/inheritance/theory_unit"},{"id":3702,"name":"quiz","url":"/courses/python-oop-basics/lessons/inheritance/quiz_unit"},{"id":3705,"name":"exercise","url":"/courses/python-oop-basics/lessons/inheritance/exercise_unit"}],"links":[{"id":424115,"name":"Наследование","url":"https://docs.python.org/3/tutorial/classes.html#inheritance"}],"ordered_units":[{"id":3701,"name":"theory","url":"/courses/python-oop-basics/lessons/inheritance/theory_unit"},{"id":3702,"name":"quiz","url":"/courses/python-oop-basics/lessons/inheritance/quiz_unit"},{"id":3705,"name":"exercise","url":"/courses/python-oop-basics/lessons/inheritance/exercise_unit"}],"id":1713,"slug":"inheritance","state":"approved","name":"Наследование","course_order":800,"goal":"Познакомимся с механизмом наследования классов в Python. Узнаем, как наследование помогает повторно использовать объектный код","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"Все классы, которые мы рассматривали до этого, создавались \"с нуля\". И до тех пор, пока описываемые классами сущности мало похожи друг на друга, создание абсолютно новых классов работает отлично. Но что делать, если мы хотим, чтобы пара классов содержала один и тот же метод — не одноименный, а именно копию?\n\nКонечно же, мы можем при объявлении класса вместо объявления метода по месту поместить в атрибут ссылку на существующую функцию. И это даже сработает. Но когда таковых методов станет несколько, уследить за тем, что и куда копируется, станет очень сложно. К счастью, есть способ лучше.\n\nЯзыки, реализующие инструментарий для объектно ориентированного программирования, включая использование классов, предоставляют и механизм *наследования*. Python — один из таких языков. Поэтому классы в Python можно *наследовать*.\n\nКогда один класс становится наследником другого, то все атрибуты *класса-предка (надкласса, superclass)* становятся доступны *классу-потомку (подклассу, subclass)* — наследуются (достаются в наследство).\n\n## Что дает наследование\n\nНаследование позволяет выделить *общее для нескольких классов* поведение и вынести его в отдельную сущность. То есть наследование является средством *переиспользования кода (code reuse)* — использования существующего кода для решения новых задач.\n\nНаследование позволяет получить новый класс, *немного отличающийся* от старого. При этом нам не нужно иметь доступ к коду исходного класса, а значит с помощью наследования мы можем *адаптировать* (использовать повторно) под наши задачи, в том числе и чужие классы.\n\nКак обычно, рассмотрим пример:\n\n```python\n# этот класс у нас уже был\nclass Counter:\n def __init__(self):\n self.value = 0\n\n def inc(self):\n self.value += 1\n\n def dec(self):\n self.value -= 1\n\n\n# А этот класс - новый. Наследник Counter\nclass NonDecreasingCounter(Counter): # в скобках указан класс-предок\n def dec(self):\n pass\n```\n\nЕсли мы выполним эти объявления классов и посмотрим на поведение экземпляра `NonDecreasingCounter`, то увидим, что он работает как `Counter` — имеет те же методы и атрибуты (правда, при вызове метода `.dec` новый счетчик не изменяет текущее значение):\n\n```python\nn = NonDecreasingCounter()\nn.inc()\nn.inc()\nn.value # 2\nn.dec()\nn.value # 2\n```\n\nВ объявлении `NonDecreasingCounter` присутствует метод `dec`, а вот откуда взялись `value` и `inc`? Они были взяты от предка — класса `Counter`. Данный факт даже можно пронаблюдать:\n\n```python\nn.dec\n# <bound method NonDecreasingCounter.dec of <__main__.NonDecreasingCounter object at 0x7f361b29c940>>\nn.inc\n# <bound method Counter.inc of <__main__.NonDecreasingCounter object at 0x7f361b29c940>>\n```\n\nМетод `dec` — метод класса `NonDecreasingCounter`, связанный с конкретным экземпляром `NonDecreasingCounter`. А вот `inc` — метод класса `Counter`, хоть и связанный с все тем же экземпляром класса-потомка.\n\nЗдесь вы можете увидеть сходство с взаимоотношениями между классом и его экземпляром: если экземпляр получает свой собственный атрибут, то этот атрибут заменяет атрибут класса. Точно так же объявления в классе-потомке заменяют собой атрибуты класса-предка, если имя используется то же самое — говорят, *переопределяют (override)*.\n\nИ, как и в случае с объектом, который может использовать все содержимое класса и заменять только небольшую часть атрибутов (или добавлять новые.), так и потомок по умолчанию получает *все атрибуты предка*, часть из которых может изменить.\n\n## Все будет `super()`\n\nПредставим, что нас в целом устраивает класс `Counter` из предыдущего примера, но мы хотим при вызове `inc` увеличивать значение дважды. Мы могли бы заменить в потомке весь метод и прописать внутри нового метода `self.value += 2`. Но если бы позже что-то поменялось в исходном классе `Counter`, то эти изменения не коснулись бы нашего метода.\n\nПолучается, что нам внутри метода потомка нужно получить доступ к методу предка. Методу с тем же именем. Если мы просто обратимся к `self.inc`, то получим ссылку на новый метод, ведь мы его *переопределили*.\n\nТут нам на помощь приходит специальная функция `super`. Функция `super` так названа в честь названия класса-предка: \"superclass\":\n\n```python\nclass DoubleCounter(Counter):\n def inc(self):\n super().inc()\n super().inc()\n```\n\nВызов `super` здесь заменяет обращение к `self`. При этом вы фактически обращаетесь к \"памяти предков\": получаете ссылку на атрибут предка. Более того, в данном случае, `super().inc` - это *связанный с текущим экземпляром* метод, то есть полноценная \"оригинальная версия\" из класса-предка. Если бы вы вдруг решили вручную вызвать метод класса предка, то вам бы пришлось использовать его не связанную версию:\n\n```python\nclass DoubleCounter(Counter):\n def inc(self):\n Counter.inc(self) # явно обращаемся к методу класса предка\n Counter.inc(self) # и передаем ссылку на экземпляр\n```\n\nВызов `super` вместо явного вызова предка хорош не только тем, что автоматически связывает методы. При смене предка (такое бывает) в описании класса `super` учтет изменения, и вы получите доступ к поведению нового предка. Удобно.\n\n`super` работает не только с методами, но и с атрибутами классов:\n\n```python\nclass A:\n x = \"A\"\n\n\nclass B(A):\n x = \"B\"\n\n def super_x(self):\n return super().x\n\n\nB().x # 'B'\nB().super_x() # 'A'\n```\n\nНо важно помнить, что `super` работает именно с классами. Вы *не сможете* получить доступ к атрибутам, которые добавляются в объект уже после того, как тот будет создан.\n\n```python\nclass A:\n x = \"A\"\n\n\nclass B(A):\n def super_x(self):\n return super().x\n\n def super_y(self):\n return super().y\n\n\na = A()\nb = B()\n\n# добавляем атрибут после создания объекта\na.y = 42\n\nb.super_x() # 'A'\nb.super_y() # AttributeError ...\n```\n\n## Вызов инициализатора суперкласса с `super()`\n\nПри наследовании классов часто возникает необходимость не только добавить новые атрибуты или методы, но и расширить или изменить инициализацию объекта. В этом случае очень важно корректно вызвать конструктор суперкласса, чтобы все атрибуты и состояние, которые должны быть наследованы, были правильно установлены.\n\nИспользование `super()` в `__init__` позволяет нам вызвать конструктор суперкласса, что гарантирует, что весь необходимый код инициализации будет выполнен:\n\n```python\nclass Counter:\n def __init__(self):\n self.value = 0\n\n def inc(self):\n self.value += 1\n\n def dec(self):\n self.value -= 1\n\n\nclass NonDecreasingCounter(Counter):\n def __init__(self):\n super().__init__() # Вызываем конструктор предка\n self.non_decreasing = True # Дополнительный атрибут для наследника\n\n def dec(self):\n if self.non_decreasing:\n print(\"Уменьшение значения запрещено.\")\n else:\n super().dec() # Вызываем метод dec предка, если уменьшение разрешено\n\n\nn = NonDecreasingCounter()\nn.inc()\nprint(n.value) # 1\nn.dec() # Уменьшение значения запрещено.\nprint(n.value) # 1\n\nn.non_decreasing = False\nn.dec()\nprint(n.value) # 0\n```\n\nВ этом примере метод `__init__` в `NonDecreasingCounter` вызывает метод `__init__` предка `Counter` с помощью `super()`. Это гарантирует, что атрибут `value` инициализируется как в `Counter`. Класс `NonDecreasingCounter` добавляет дополнительный атрибут `non_decreasing` и изменяет поведение метода `dec`, чтобы контролировать, может ли счетчик уменьшаться. Это демонстрирует, как можно расширить и настроить поведение классов при наследовании.\n\nВ контексте множественного наследования использование `super()` становится еще более важным, так как оно гарантирует, что все конструкторы суперклассов вызываются в правильном порядке. Это предотвращает проблемы с инициализацией и позволяет каждому классу в иерархии наследования вносить свой вклад в конечное состояние объекта.\n\n## Наследование и `object`\n\nВ прошлом мы не указывали предка в объявлениях классов, то есть писали так:\n\n```python\nclass Foo:\n pass\n```\n\nВ Python3 такая запись равнозначна записи `class Foo(object):`. То есть, если класс-предок не указан, то таковым считается `object` — самый базовый класс в Python. Сейчас, в эпоху повсеместного использования Python3, указывать или не указывать наследование от `object` — дело вкуса.\n\nА вот в Python2 `class Foo:` и `class Foo(object):` не были равнозначны. И это приводило к очень неприятным последствиям. Поэтому до сих пор можно встретить линтеры, которые жалуются на код без `(object)` — вдруг вы захотите запустить код на старом добром втором Python?\n\nВам решать, будете ли вы указывать предка `object` или отключите соответствующее предупреждение. Благо в Python3 оба варианта приемлемы и не противоречат друг другу.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":3514,"name":"theory","url":"/courses/python-oop-basics/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":3514,"name":"theory","url":"/courses/python-oop-basics/lessons/intro/theory_unit"}],"id":1643,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Узнаем о целях курса","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"## Изобретаем ООП\n\nБольшая часть кода, который мы до этого момента рассматривали, была написана в процедурном стиле: мы использовали переменные и код, их изменяющий. В этом курсе мы научимся писать *объектный код*. Объектно-ориентированное программирование (ООП) расширяет *процедурное программирование*, которое является ступенью развития *императивного программирования*. Позволим себе маленький экскурс в историю и по шагам подойдем к самой идее ООП.\n\nИтак, *императивное программирование* — описание в виде кода последовательности действий, выполнив которые, компьютер выдаст нужный нам результат. Действия выполняются друг за другом, данные от действия к действию передаются с помощью переменных.\n\nВ какой-то момент появляется необходимость выбирать между несколькими путями достижения результата или же повторить некий набор действий несколько раз. Тут на сцену выходит *структурное программирование*, которое предоставляет нам *управляющие структуры* — циклы, условные конструкции.\n\nПрограммы становятся все больше и со временем становятся слишком сложны для понимания — слишком много действий записано подряд, слишком велика вложенность циклов и условий. Тут на помощь приходит процедурное программирование. И приносит с собой возможность взять самостоятельный кусок кода, снабдить именем, убрать с глаз долой и дальше использовать только это самое имя — так появляются процедуры. В дальнейшем процедуры учатся принимать параметры и возвращать результат вместо использования внешних переменных.\n\nПоявление процедур — очень важный шаг. С этого момента программист может *расширять язык*, дополнять его новыми \"словами\". Новые слова делают код более понятным, ведь они, как правило, тесно связаны с предметной областью. Кода становится меньше, но каждый шаг начинает нести больший смысл: мелкие детали, вроде сложения чисел, прячутся за именами, означающими действия более высокого уровня — мы уже оперируем не числами, а *сущностями*, вроде товаров в корзине, пользователей системы, персонажей игры.\n\nОдновременно с процедурами появляются и *структуры данных*, позволяющие эти самые сущности собирать из отдельных элементов, типа строк и чисел. И тут есть небольшая путаница: структурное программирование названо не в честь структур данных, а именно в честь управляющих структур.\n\nТеперь мы имеем процедуры и сущности, которыми они оперируют. И довольно часто одно неотделимо от другого. Процедуры, работающие с персонажем игры, работают только с ним, но не применимы к товарам в корзине. К тому же нам все время нужно где-то хранить эти самые структуры. Вот тут-то и появляется ООП со словами: «Вы можете объединить процедуры и данные в единое целое, которое мы назовем *объект*.».\n\n## Сложность, абстракция, слои, протекание\n\nСокрытие деталей реализации за неким понятием и оперирование в дальнейшем этим понятием как цельной сущностью, называется *абстрагированием* — получением *абстракции*. Абстракция позволяет нам думать о важных качествах сущности, и напротив — не думать о том, что менее существенно. Например, нам удобно \"просто перемещать\" персонажа игры по игровому полю и не думать о представлении координат персонажа в памяти.\n\nВведение абстракций, так же как и добавление в язык управляющих структур и процедур, позволяет *управлять сложностью*. Если взять одну большую задачу и сравнить два решения: структурную программу и написанную в объектном стиле, то строчек кода в первой может оказаться даже меньше. Но каждый отдельно взятый кусок объектной программы будет проще понять, ведь в структурной программе везде видны детали реализации и за ними очень сложно увидеть общую логику.\n\n> Разница в удобстве написания и чтения кода будет видна и при сравнении структурного кода с процедурным. Структуры данных тоже упрощают написание сложного кода. Ведь процедуры и структуры данных — такие же средства абстрагирования.\n\nПроцесс абстрагирования редко завершается: сначала вводятся одни абстракции (персонажи, противники, игровое поле), затем это все прячется за новым *уровнем (слоем) абстракции* (армия игрока, осада замка, битва в космосе), а затем за еще более высоким (игровая сессия, игра). Кроме того, возможность что-то обобщить и абстрагировать может возникать и при изменении существующего кода.\n\nХорошее разделение на уровни абстракции позволяет на каждом уровне рассуждать только о сущностях этого уровня абстракции — без необходимости спускаться ниже или подниматься выше. Если же, находясь на одном уровне, приходится заглядывать на другие, то мы имеем дело с \"протекающими\" (\"дырявыми\", \"leaking\") абстракциями.\n\nКак говорил классик Джоэл Спольски: «Все нетривиальные абстракции протекают». При этом вы можете работать с этими «протечками» и контролировать их. Если введение какой-то абстракции способно *уменьшить сложность* в одном месте без сильного увеличения сложности программы в целом, то стоит подумать о том, чтобы абстракцию ввести. В этом обдумывании и заключается управление сложностью — важная часть работы программиста.\n\n## Разные сложности\n\nВыше мы много раз использовали слово «сложность». Важно уточнить: в этом уроке речь не шла о сложности выполнения программы с точки зрения компьютера. Компьютеру тем проще выполнять программу, чем проще код, поэтому с его точки зрения идеальная программа — императивная, без всех этих объектов и процедур. Вот только код гораздо чаще читают люди, чем компьютер. Поэтому нам нужно думать о сложности кода для понимания человеком.\n"},"id":202,"slug":"python-oop-basics","challenges_count":5,"name":"Python: Введение в ООП","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"На этом курсе вы изучите концепцию ООП — объектно-ориентированного программирования. Вы познакомитесь с такими понятиями как классы и объекты, раскроете основные принципы ООП как инкапсуляция, полиморфизм и наследование. В итоге научитесь описывать сущности предметной области, поймете как изнутри работают объекты в Python и как использовать исключения в коде. Знания из этого курса помогут писать более структурированный и гибкий код, который легко дополнять и изменять.","kind":"basic","updated_at":"2026-01-20T11:45:34.730Z","language":"python","duration_cache":39780,"skills":["Грамотно использовать контекст self в зависимости от ситуации","Описывать сущности предметной области с помощью объектов и классов","Понимать, как работают объекты в Python на самом низком уровне","Использовать исключения в своем коде"],"keywords":["классы","инкапсуляция","связывание","исключения","конструктор"],"lessons_count":10,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NzM1NSwicHVyIjoiYmxvYl9pZCJ9fQ==--7fa7469efda4b01f5b5933ec2e041ea1fab0b6a1/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[{"stack":{"id":7,"slug":"python","title":"Python-разработчик","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":10,"duration_in_months":10},"id":7,"slug":"python","title":"Python-разработчик ","subtitle":"Изучите Python, Django, REST и Fast API для создания веб-приложений","subtitle_for_lists":"Изучите Python, Django, REST и Fast API для создания веб-приложений","locale":"ru","current":true,"duration_in_months_text":"10 месяцев","stack_slug":"python","price_text":"от 6 792 ₽","duration_text":"10 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczMSwicHVyIjoiYmxvYl9pZCJ9fQ==--f5df4883f3f678321cb4fa96e9ce657bd5ee1adf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png"},{"stack":{"id":67,"slug":"python-oop","title":"ООП на Python","audience":"for_programmers","start_type":"anytime","pricing_model":"subscription","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":4350,"duration_in_months":2},"id":120,"slug":"python-oop","title":"ООП на Python","subtitle":"Навык понимания архитектуры и чистого кода, позволяющий проходить собеседования, решать задачи и увеличивать зарплату","subtitle_for_lists":"Изучите архитектуру и чистый код на Python","locale":"ru","current":true,"duration_in_months_text":"2 месяца","stack_slug":"python-oop","price_text":"от 3 900 ₽","duration_text":"2 месяца","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc0OSwicHVyIjoiYmxvYl9pZCJ9fQ==--846349326718432328cf5c0677091aca67f80af3/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Developer%20activity-amico%20(1).png"},{"stack":{"id":220,"slug":"qa-auto-engineer-python","title":"Автоматизатор тестирования на Python","audience":"for_programmers","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":100,"duration_in_months":6},"id":331,"slug":"qa-auto-engineer-python","title":"Автоматизатор тестирования на Python","subtitle":"Изучите Python, фреймворки для тестирования, автоматизация UI и API","subtitle_for_lists":"Изучите Python, фреймворки для тестирования, автоматизация UI и API","locale":"ru","current":true,"duration_in_months_text":"6 месяцев","stack_slug":"qa-auto-engineer-python","price_text":"от 4 281 ₽","duration_text":"6 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyMCwicHVyIjoiYmxvYl9pZCJ9fQ==--71cd9d863b21d7bfbd927cf623a7a2baaf4530ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-cuate.png"},{"stack":{"id":466,"slug":"middle-python","title":"Middle-python разработчик","audience":"for_programmers","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"not_finished","order":2001,"duration_in_months":5},"id":594,"slug":"middle-python","title":"Мидл-python разработчик","subtitle":"Углубите знания Python, архитектуры приложений и работы с базами данных","subtitle_for_lists":"Углубите знания Python, архитектуры приложений и работы с базами данных","locale":"ru","current":true,"duration_in_months_text":"5 месяцев","stack_slug":"middle-python","price_text":"от 4 050 ₽","duration_text":"5 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIyMiwicHVyIjoiYmxvYl9pZCJ9fQ==--0e824331c2dcddbe1fa1aaa4188500e364c8c38c/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-bro.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":false,"accessToCourseExists":false},"url":"/courses/python-oop-basics/lessons/inheritance/theory_unit","version":"8f286f6358a90a7bef2263b3a6edf5a90a94fa42","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Python: Введение в ООП</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Наследование</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Наследование","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"Python: Введение в ООП"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>Все классы, которые мы рассматривали до этого, создавались "с нуля". И до тех пор, пока описываемые классами сущности мало похожи друг на друга, создание абсолютно новых классов работает отлично. Но что делать, если мы хотим, чтобы пара классов содержала один и тот же метод — не одноименный, а именно копию?</p>
<p>Конечно же, мы можем при объявлении класса вместо объявления метода по месту поместить в атрибут ссылку на существующую функцию. И это даже сработает. Но когда таковых методов станет несколько, уследить за тем, что и куда копируется, станет очень сложно. К счастью, есть способ лучше.</p>
<p>Языки, реализующие инструментарий для объектно ориентированного программирования, включая использование классов, предоставляют и механизм <em>наследования</em>. Python — один из таких языков. Поэтому классы в Python можно <em>наследовать</em>.</p>
<p>Когда один класс становится наследником другого, то все атрибуты <em>класса-предка (надкласса, superclass)</em> становятся доступны <em>классу-потомку (подклассу, subclass)</em> — наследуются (достаются в наследство).</p>
<h2 id="heading-2-1">Что дает наследование</h2>
<p>Наследование позволяет выделить <em>общее для нескольких классов</em> поведение и вынести его в отдельную сущность. То есть наследование является средством <em>переиспользования кода (code reuse)</em> — использования существующего кода для решения новых задач.</p>
<p>Наследование позволяет получить новый класс, <em>немного отличающийся</em> от старого. При этом нам не нужно иметь доступ к коду исходного класса, а значит с помощью наследования мы можем <em>адаптировать</em> (использовать повторно) под наши задачи, в том числе и чужие классы.</p>
<p>Как обычно, рассмотрим пример:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code"># этот класс у нас уже был
class Counter:
def __init__(self):
self.value = 0
def inc(self):
self.value += 1
def dec(self):
self.value -= 1
# А этот класс - новый. Наследник Counter
class NonDecreasingCounter(Counter): # в скобках указан класс-предок
def dec(self):
pass</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Если мы выполним эти объявления классов и посмотрим на поведение экземпляра <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code>, то увидим, что он работает как <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code> — имеет те же методы и атрибуты (правда, при вызове метода <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">.dec</code> новый счетчик не изменяет текущее значение):</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">n = NonDecreasingCounter()
n.inc()
n.inc()
n.value # 2
n.dec()
n.value # 2</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В объявлении <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code> присутствует метод <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">dec</code>, а вот откуда взялись <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">value</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">inc</code>? Они были взяты от предка — класса <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code>. Данный факт даже можно пронаблюдать:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">n.dec
# <bound method NonDecreasingCounter.dec of <__main__.NonDecreasingCounter object at 0x7f361b29c940>>
n.inc
# <bound method Counter.inc of <__main__.NonDecreasingCounter object at 0x7f361b29c940>></code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Метод <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">dec</code> — метод класса <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code>, связанный с конкретным экземпляром <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code>. А вот <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">inc</code> — метод класса <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code>, хоть и связанный с все тем же экземпляром класса-потомка.</p>
<p>Здесь вы можете увидеть сходство с взаимоотношениями между классом и его экземпляром: если экземпляр получает свой собственный атрибут, то этот атрибут заменяет атрибут класса. Точно так же объявления в классе-потомке заменяют собой атрибуты класса-предка, если имя используется то же самое — говорят, <em>переопределяют (override)</em>.</p>
<p>И, как и в случае с объектом, который может использовать все содержимое класса и заменять только небольшую часть атрибутов (или добавлять новые.), так и потомок по умолчанию получает <em>все атрибуты предка</em>, часть из которых может изменить.</p>
<h2 id="heading-2-2">Все будет <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super()</code></h2>
<p>Представим, что нас в целом устраивает класс <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code> из предыдущего примера, но мы хотим при вызове <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">inc</code> увеличивать значение дважды. Мы могли бы заменить в потомке весь метод и прописать внутри нового метода <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">self.value += 2</code>. Но если бы позже что-то поменялось в исходном классе <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code>, то эти изменения не коснулись бы нашего метода.</p>
<p>Получается, что нам внутри метода потомка нужно получить доступ к методу предка. Методу с тем же именем. Если мы просто обратимся к <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">self.inc</code>, то получим ссылку на новый метод, ведь мы его <em>переопределили</em>.</p>
<p>Тут нам на помощь приходит специальная функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code>. Функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> так названа в честь названия класса-предка: "superclass":</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class DoubleCounter(Counter):
def inc(self):
super().inc()
super().inc()</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Вызов <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> здесь заменяет обращение к <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">self</code>. При этом вы фактически обращаетесь к "памяти предков": получаете ссылку на атрибут предка. Более того, в данном случае, <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super().inc</code> - это <em>связанный с текущим экземпляром</em> метод, то есть полноценная "оригинальная версия" из класса-предка. Если бы вы вдруг решили вручную вызвать метод класса предка, то вам бы пришлось использовать его не связанную версию:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class DoubleCounter(Counter):
def inc(self):
Counter.inc(self) # явно обращаемся к методу класса предка
Counter.inc(self) # и передаем ссылку на экземпляр</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Вызов <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> вместо явного вызова предка хорош не только тем, что автоматически связывает методы. При смене предка (такое бывает) в описании класса <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> учтет изменения, и вы получите доступ к поведению нового предка. Удобно.</p>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> работает не только с методами, но и с атрибутами классов:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class A:
x = "A"
class B(A):
x = "B"
def super_x(self):
return super().x
B().x # 'B'
B().super_x() # 'A'</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Но важно помнить, что <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super</code> работает именно с классами. Вы <em>не сможете</em> получить доступ к атрибутам, которые добавляются в объект уже после того, как тот будет создан.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class A:
x = "A"
class B(A):
def super_x(self):
return super().x
def super_y(self):
return super().y
a = A()
b = B()
# добавляем атрибут после создания объекта
a.y = 42
b.super_x() # 'A'
b.super_y() # AttributeError ...</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<h2 id="heading-2-3">Вызов инициализатора суперкласса с <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super()</code></h2>
<p>При наследовании классов часто возникает необходимость не только добавить новые атрибуты или методы, но и расширить или изменить инициализацию объекта. В этом случае очень важно корректно вызвать конструктор суперкласса, чтобы все атрибуты и состояние, которые должны быть наследованы, были правильно установлены.</p>
<p>Использование <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super()</code> в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">__init__</code> позволяет нам вызвать конструктор суперкласса, что гарантирует, что весь необходимый код инициализации будет выполнен:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Counter:
def __init__(self):
self.value = 0
def inc(self):
self.value += 1
def dec(self):
self.value -= 1
class NonDecreasingCounter(Counter):
def __init__(self):
super().__init__() # Вызываем конструктор предка
self.non_decreasing = True # Дополнительный атрибут для наследника
def dec(self):
if self.non_decreasing:
print("Уменьшение значения запрещено.")
else:
super().dec() # Вызываем метод dec предка, если уменьшение разрешено
n = NonDecreasingCounter()
n.inc()
print(n.value) # 1
n.dec() # Уменьшение значения запрещено.
print(n.value) # 1
n.non_decreasing = False
n.dec()
print(n.value) # 0</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В этом примере метод <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">__init__</code> в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code> вызывает метод <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">__init__</code> предка <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code> с помощью <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super()</code>. Это гарантирует, что атрибут <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">value</code> инициализируется как в <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Counter</code>. Класс <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">NonDecreasingCounter</code> добавляет дополнительный атрибут <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">non_decreasing</code> и изменяет поведение метода <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">dec</code>, чтобы контролировать, может ли счетчик уменьшаться. Это демонстрирует, как можно расширить и настроить поведение классов при наследовании.</p>
<p>В контексте множественного наследования использование <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">super()</code> становится еще более важным, так как оно гарантирует, что все конструкторы суперклассов вызываются в правильном порядке. Это предотвращает проблемы с инициализацией и позволяет каждому классу в иерархии наследования вносить свой вклад в конечное состояние объекта.</p>
<h2 id="heading-2-4">Наследование и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">object</code></h2>
<p>В прошлом мы не указывали предка в объявлениях классов, то есть писали так:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">class Foo:
pass</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>В Python3 такая запись равнозначна записи <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">class Foo(object):</code>. То есть, если класс-предок не указан, то таковым считается <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">object</code> — самый базовый класс в Python. Сейчас, в эпоху повсеместного использования Python3, указывать или не указывать наследование от <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">object</code> — дело вкуса.</p>
<p>А вот в Python2 <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">class Foo:</code> и <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">class Foo(object):</code> не были равнозначны. И это приводило к очень неприятным последствиям. Поэтому до сих пор можно встретить линтеры, которые жалуются на код без <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">(object)</code> — вдруг вы захотите запустить код на старом добром втором Python?</p>
<p>Вам решать, будете ли вы указывать предка <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">object</code> или отключите соответствующее предупреждение. Благо в Python3 оба варианта приемлемы и не противоречат друг другу.</p></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/python?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">10 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Python-разработчик </p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите Python, Django, REST и Fast API для создания веб-приложений</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzczMSwicHVyIjoiYmxvYl9pZCJ9fQ==--f5df4883f3f678321cb4fa96e9ce657bd5ee1adf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png" alt="Python-разработчик " loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 6 792 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/python-oop?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">2 месяца</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">ООП на Python</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите архитектуру и чистый код на Python</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc0OSwicHVyIjoiYmxvYl9pZCJ9fQ==--846349326718432328cf5c0677091aca67f80af3/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Developer%20activity-amico%20(1).png" alt="ООП на Python" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/qa-auto-engineer-python?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">6 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Автоматизатор тестирования на Python</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите Python, фреймворки для тестирования, автоматизация UI и API</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzkyMCwicHVyIjoiYmxvYl9pZCJ9fQ==--71cd9d863b21d7bfbd927cf623a7a2baaf4530ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Bug%20fixing-cuate.png" alt="Автоматизатор тестирования на Python" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 4 281 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/middle-python?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">5 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Мидл-python разработчик</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Углубите знания Python, архитектуры приложений и работы с базами данных</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NTIyMiwicHVyIjoiYmxvYl9pZCJ9fQ==--0e824331c2dcddbe1fa1aaa4188500e364c8c38c/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-bro.png" alt="Мидл-python разработчик" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 4 050 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/python-oop-basics/lessons/inheritance/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 10</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/python-oop-basics/lessons/inheritance/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-Bukl1lYy.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>