Found magic number python что это
Перейти к содержимому

Found magic number python что это

  • автор:

Замена магического числа символьной константой

В коде используется число, которое несёт какой-то определённый смысл.

Решение

Замените это число константой с человеко-читаемым названием, объясняющим смысл этого числа.

double potentialEnergy(double mass, double height)
static final double GRAVITATIONAL_CONSTANT = 9.81; double potentialEnergy(double mass, double height)
double PotentialEnergy(double mass, double height)
const double GRAVITATIONAL_CONSTANT = 9.81; double PotentialEnergy(double mass, double height)
function potentialEnergy($mass, $height)
define(«GRAVITATIONAL_CONSTANT», 9.81); function potentialEnergy($mass, $height)

def potentialEnergy(mass, height): return mass * height * 9.81
GRAVITATIONAL_CONSTANT = 9.81 def potentialEnergy(mass, height): return mass * height * GRAVITATIONAL_CONSTANT

potentialEnergy(mass: number, height: number): number
static const GRAVITATIONAL_CONSTANT = 9.81; potentialEnergy(mass: number, height: number): number

Причины рефакторинга

Магические числа — это числовые значения, встречающиеся в коде, но при этом неочевидно, что они означают. Данный антипаттерн затрудняет понимание программы и усложняет её рефакторинг.

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

Достоинства

  • Символьная константа может служить живой документацией смысла значения, которое в ней хранится.
  • Значение константы намного проще заменить, чем искать нужное число по всему коду, при этом рискуя заменить такое же число, которое в данном конкретном случае использовалось для других целей.
  • Убирает дублирование использования числа или строки по всему коду. Это особенно актуально, если значение является сложным и длинным (например, -14159 , 0xCAFEBABE ).

Полезные факты

Не все числа являются магическими.

Если предназначения чисел очевидны, их не надо заменять константами, классический пример:

for (i = 0; i

Альтернативы
  1. Иногда, магическое число можно заменить вызовом метода. Например, если у вас есть магическое число, обозначающее количество элементов коллекции, вам не обязательно использовать его для проверок последнего элемента коллекции. Вместо этого можно использовать встроенный метод получения длины коллекции.
  2. Магические числа могут быть использованы для реализации кодирования типа. Например, у вас есть два типа пользователей, и чтобы обозначить их, у вас есть числовое поле в классе, в котором для администраторов хранится число 1 , а для простых пользователей — число 2 . В этом случае имеет смысл использовать один из рефакторингов избавления от кодирования типа:
    • замена кодирования типа классом
    • замена кодирования типа подклассами
    • замена кодирования типа состоянием/стратегией

Порядок рефакторинга

  1. Объявите константу и присвойте ей значение магического числа.
  2. Найдите все упоминания магического числа.
  3. Для всех найденных чисел проверьте, согласуется ли это магическое число с предназначением константы. Если да, замените его вашей константой. Эта проверка важна, так как одно и тоже число может означать совершенно разные вещи (в этом случае, они должны быть заменены разными константами).

Устали читать?

Сбегайте за подушкой, у нас тут контента на 7 часов чтения.

Или попробуйте наш интерактивный курс. Он гораздо более интересный, чем банальный текст.

Скидки!

Этот рефакторинг — малая часть интерактивного онлайн курса по рефакторингу.

Refactoring.Guru

  • Премиум контент
    • Книга о паттернах
    • Курс по рефакторингу
    • Введение в рефакторинг
      • Чистый код
      • Технический долг
      • Когда рефакторить
      • Как рефакторить
      • Раздувальщики
        • Длинный метод
        • Большой класс
        • Одержимость элементарными типами
        • Длинный список параметров
        • Группы данных
        • Операторы switch
        • Временное поле
        • Отказ от наследства
        • Альтернативные классы с разными интерфейсами
        • Расходящиеся модификации
        • Стрельба дробью
        • Параллельные иерархии наследования
        • Комментарии
        • Дублирование кода
        • Ленивый класс
        • Класс данных
        • Мёртвый код
        • Теоретическая общность
        • Завистливые функции
        • Неуместная близость
        • Цепочка вызовов
        • Посредник
        • Неполнота библиотечного класса
        • Составление методов
          • Извлечение метода
          • Встраивание метода
          • Извлечение переменной
          • Встраивание переменной
          • Замена переменной вызовом метода
          • Расщепление переменной
          • Удаление присваиваний параметрам
          • Замена метода объектом методов
          • Замена алгоритма
          • Перемещение метода
          • Перемещение поля
          • Извлечение класса
          • Встраивание класса
          • Сокрытие делегирования
          • Удаление посредника
          • Введение внешнего метода
          • Введение локального расширения
          • Самоинкапсуляция поля
          • Замена простого поля объектом
          • Замена значения ссылкой
          • Замена ссылки значением
          • Замена поля-массива объектом
          • Дублирование видимых данных
          • Замена однонаправленной связи двунаправленной
          • Замена двунаправленной связи однонаправленной
          • Замена магического числа символьной константой
          • Инкапсуляция поля
          • Инкапсуляция коллекции
          • Замена кодирования типа классом
          • Замена кодирования типа подклассами
          • Замена кодирования типа состоянием/стратегией
          • Замена подкласса полями
          • Разбиение условного оператора
          • Объединение условных операторов
          • Объединение дублирующихся фрагментов в условных операторах
          • Удаление управляющего флага
          • Замена вложенных условных операторов граничным оператором
          • Замена условного оператора полиморфизмом
          • Введение Null-объекта
          • Введение проверки утверждения
          • Переименование метода
          • Добавление параметра
          • Удаление параметра
          • Разделение запроса и модификатора
          • Параметризация метода
          • Замена параметра набором специализированных методов
          • Передача всего объекта
          • Замена параметра вызовом метода
          • Замена параметров объектом
          • Удаление сеттера
          • Сокрытие метода
          • Замена конструктора фабричным методом
          • Замена кода ошибки исключением
          • Замена исключения проверкой условия
          • Подъём поля
          • Подъём метода
          • Подъём тела конструктора
          • Спуск метода
          • Спуск поля
          • Извлечение подкласса
          • Извлечение суперкласса
          • Извлечение интерфейса
          • Свёртывание иерархии
          • Создание шаблонного метода
          • Замена наследования делегированием
          • Замена делегирования наследованием
          • Введение в паттерны
            • Что такое Паттерн?
            • История паттернов
            • Зачем знать паттерны?
            • Критика паттернов
            • Классификация паттернов
            • Фабричный метод
            • Абстрактная фабрика
            • Строитель
            • Прототип
            • Одиночка
            • Адаптер
            • Мост
            • Компоновщик
            • Декоратор
            • Фасад
            • Легковес
            • Заместитель
            • Цепочка обязанностей
            • Команда
            • Итератор
            • Посредник
            • Снимок
            • Наблюдатель
            • Состояние
            • Стратегия
            • Шаблонный метод
            • Посетитель
            • C#
            • C++
            • Go
            • Java
            • PHP
            • Python
            • Ruby
            • Rust
            • Swift
            • TypeScript

            Что такое магические числа в программировании и как снять это заклятие

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

            Магические числа — пример плохих практик в программировании. Из этой статьи вы узнаете, почему от них надо избавляться и как это делать.

            • Что такое магические числа
            • Как избавиться от магических чисел

            Что такое магические числа

            В программировании магическими называют числа в коде, смысл которых сложно понять. Взгляните на пример.

            // показываем пользователю окончательную цену товара const showBruttoPrice = (nettoPrice) =>  const bruttoPrice = nettoPrice * 1.20; return bruttoPrice; >; 

            Это пример магического числа, потому что невозможно однозначно ответить на вопрос, почему для вычисления bruttoPrice нужно умножить nettoPrice на 1.20 . Смысл числа 1.20 приходится восстанавливать по контексту. Но при работе с большими приложениями в реальной разработке это не всегда возможно.

            Магические числа не ломают код. В примере выше пользователь увидит окончательную цену, то есть программа отработает. В чём же проблема?

            Код с магическими числами сложно понять без контекста. Это может стать проблемой для разработчиков, которые впервые видят приложение. Да и автор кода может забыть, почему использовал именно это число.

            Как избавиться от магических чисел

            Это можно сделать с помощью константы с понятным названием. То есть название константы должно передавать смысл числа.

            // указываем ставку НДС const vatRate = 1.20; const showBruttoPrice = (nettoPrice) =>  const bruttoPrice = nettoPrice * vatRate; return bruttoPrice; >; 

            Очевидное указание ставки НДС делает код более понятным.

            Код с магическими числами сложно поддерживать и расширять. Например, если магазин продаёт товары людям из разных стран, магические числа приводят к дублированию:

            // в разных странах разные ставки НДС const showBruttoPrice = (nettoPrice, country) =>  let bruttoPrice; if (country === 'Russia')  bruttoPrice = nettoPrice * 1.20; > if (country === 'Germany')  bruttoPrice = nettoPrice * 1.19; > // стран может быть 5, 20 или 50 // для каждой придётся использовать // своё магическое число // . return bruttoPrice; >; 

            Проблему решает избавление от магических чисел:

            const getVatRate = (country) =>  // получаем ставку НДС для конкретной страны из // базы данных или из внешнего источника >; const showBruttoPrice = (nettoPrice, country) =>  // определяем ставку НДС вместо того, // чтобы указывать её с помощью магических чисел const vatRate = getVatRate(country); // определяем окончательную цену const bruttoPrice = nettoPrice * vatRate; return bruttoPrice; >; 
            • Магические числа — плохая практика в программировании
            • Обычно магические числа не ломают код, а делают его менее понятным
            • Чтобы избавиться от магических чисел, достаточно использовать константы или переменные с понятными названиями

            Чистое зло Python

            Темные силы не дремлют. Они пробираются в дивное королевство Python и используют черную магию, чтобы осквернить главную реликвию — чистый код. Однако опасны не только злые чары.

            Сегодня я расскажу о страшных чудовищах, которые, возможно, уже обжились в вашем коде и готовы устанавливать свои правила. Здесь нужен герой, который защитит безмятежный мир от злобных тварей. И именно вы станете тем, кто сразится с ними!

            Всем героям, однако, нужно магическое снаряжение, которое верой и правдой послужит им в грандиозных битвах. К счастью, с нами будет линтер wemake-python-styleguide. Он станет тем самым острым оружием и надежным соратником.

            Все готово, выступаем в поход!

            Пожиратели пространства

            А вот и первые проблемы. Жители стали замечать, как нечто лакомится пробелами, а операторы обретают причудливые формы:

            x = 1 x -=- x print(x) # => 2 o = 2 o+=+o print(o) # => 4 print(3 --0-- 5 == 8) # => True

            Эти странные операторы состоят из совершенно обычных и дружественных нам -= и — . Посмотрим, сможет ли наш линтер найти их:

             5:5 E225 missing whitespace around operator x -=- x ^ 5:5 WPS346 Found wrong operation sign x -=- x ^ 10:2 E225 missing whitespace around operator o+=+o ^ 14:10 E225 missing whitespace around operator print(3 --0-- 5 == 8) ^ 14:10 WPS346 Found wrong operation sign print(3 --0-- 5 == 8) ^ 14:11 WPS345 Found meaningless number operation print(3 --0-- 5 == 8) ^ 14:12 E226 missing whitespace around arithmetic operator print(3 --0-- 5 == 8) ^ 14:13 WPS346 Found wrong operation sign print(3 --0-- 5 == 8) ^

            Настала пора обнажить меч и принять бой:

            x = 1 x += x o = 2 o += o print(3 + 5 == 8)

            Враг повержен, и сразу вернулись прежние чистота и ясность!

            Загадочные точки

            Теперь жители сообщают о появлении странных глифов. О, смотрите-ка, вот и они!

            print(0..__eq__(0)) # => True print(. __eq__(((. )))) # => True

            Что же здесь происходит? Кажется, там замешаны типы данных float и Ellipsis , но лучше удостовериться.

             21:7 WPS609 Found direct magic attribute usage: __eq__ print(0..__eq__(0)) ^ 21:7 WPS304 Found partial float: 0. print(0..__eq__(0)) ^ 24:7 WPS609 Found direct magic attribute usage: __eq__ print(. __eq__(((. )))) ^

            Ага, теперь понятно. Действительно, эти точки — краткая запись значений типа float (в первом случае) и Ellipsis (во втором). И в обоих случаях происходит обращение к методу, также через точку. Давайте посмотрим, что же скрывалось за этими знаками:

            print(0.0 == 0) print(. == . )

            На этот раз все обошлось, но впредь не сравнивайте константы друг с другом, дабы не накликать беду.

            Кривая дорожка

            А между тем у нас новая напасть — значения из некоторых веток в функции никогда не возвращаются. Давайте разберемся, в чем дело.

            def some_func(): try: return 'from_try' finally: return 'from_finally' some_func() # => 'from_finally'

            Функция не возвращает значение ‘from_try’ из-за закравшейся в код ошибки. «Как ее исправить?» — изумленно спросите вы.

            31:5 WPS419 Found `try`/`else`/`finally` with multiple return paths try: ^

            Оказывается, wemake-python-styleguide знает ответ: никогда не возвращайте значение из ветки finally . Послушаемся совета.

            def some_func(): try: return 'from_try' finally: print('now in finally')

            Мрачный СИ-луэт прошлого

            Древнее существо пробуждается. Уже несколько десятилетий никто не видел его, но теперь оно вернулось.

            a = [(0, 'Hello'), (1, 'world')] for ['>']['>'>'>'], x in a: print(x)

            Что тут происходит? Известно, что в циклах можно распаковывать разные значения: почти любые валидные в Python выражения.

            Правда, многое из этого примера нам не следовало бы делать:

             44:1 WPS414 Found incorrect unpacking target for ['>']['>'>'>'], x in a: ^ 44:5 WPS405 Found wrong `for` loop variable definition for ['>']['>'>'>'], x in a: ^ 44:11 WPS308 Found constant compare for ['>']['>'>'>'], x in a: ^ 44:14 E225 missing whitespace around operator for ['>']['>'>'>'], x in a: ^ 44:21 WPS111 Found too short name: x for ['>']['>'>'>'], x in a: ^

            Теперь разберемся с [‘>’][‘>’>’>’] . Похоже, что данное выражение можно просто переписать как [‘>’][0] , поскольку у выражения ‘>’ > ‘>’ значение False . А False и 0 — одно и тоже.

            Метки Темного Колдуна

            Насколько сложным может быть выражение на Python? Наверняка такие конструкции — происки злых сил. Это Темный Колдун оставляет свои замысловатые метки во всех классах, к которым прикасается:

            class _: # Видите эти четыре метки? _: [(). ()] = <((). ()): <(). ()>>[((). ())] print(_._) # и этот оператор выглядит знакомо # =>

            Что же за ними скрывается? Похоже, у каждой метки свое значение:

            • Объявление и указание типа: _: [(). ()] = .
            • Определение словаря, где значение — набор данных: = < ((). ()): > .
            • Ключ: [((). ())] .

            В мире людей подобная запись не имеет никакого смысла и безвредна, однако в королевстве Python она может стать оружием в злых руках. Давайте ее уберем:

             55:5 WPS122 Found all unused variables definition: _ _: [(). ()] = <((). ()): <(). ()>>[((). ())] ^ 55:5 WPS221 Found line with high Jones Complexity: 19 _: [(). ()] = <((). ()): <(). ()>>[((). ())] ^ 55:36 WPS417 Found non-unique item in hash: () _: [(). ()] = <((). ()): <(). ()>>[((). ())] ^ 57:7 WPS121 Found usage of a variable marked as unused: _ print(_._) # и этот оператор выглядит знакомо ^

            Теперь, когда мы удалили или зарефакторили это выражение (со значением 19 по метрике сложности Jones Complexity), от метки Темного Колдуна в бедном классе не осталось и следа. Очередные ростки зла уничтожены.

            Метамагия

            Однако теперь наши классы связались с какими-то дурными типами, и те оказывают на них пагубное влияние.

            Сейчас классы выдают очень странные результаты:

            class Example(type((lambda: 0.)())): . print(Example(1) + Example(3)) # => 4.0

            Почему 1 + 3 равно 4.0 , а не 4 ? Чтобы это выяснить, рассмотрим поближе часть с type((lambda: 0.)()) :

            • (lambda: 0.)() просто равно 0. , а это просто иная запись 0.0 .
            • type(0.0) возвращает тип float .
            • когда мы пишем Example(1) , это значение преобразуется в Example(1.0) внутри класса.
            • Example(1.0) + Example(3.0) = Example(4.0) .

            Давайте убедимся, что наш линтер-клинок по-прежнему остр:

             63:15 WPS606 Found incorrect base class class Example(type((lambda: 0.)())): ^ 63:21 WPS522 Found implicit primitive in a form of lambda class Example(type((lambda: 0.)())): ^ 63:29 WPS304 Found partial float: 0. class Example(type((lambda: 0.)())): ^ 64:5 WPS428 Found statement that has no effect . ^ 64:5 WPS604 Found incorrect node inside `class` body . ^

            Со всем разобрались, теперь наши классы в безопасности. Можем двигаться дальше.

            Иллюзии

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

            a = ['a', 'b'] print(set(x + '!' for x in a)) # => print(set((yield x + '!') for x in a)) # =>

            Это одно из хтонических чудовищ Python — да, они все-таки существуют и тут. Учитывая, что в python3.8 такая конструкция приведет к SyntaxError , yield и yield from следует использовать только в функциях-генераторах.

            А вот и отчет об инциденте:

             73:7 C401 Unnecessary generator - rewrite as a set comprehension. print(set(x + '!' for x in a)) ^ 76:7 C401 Unnecessary generator - rewrite as a set comprehension. print(set((yield x + '!') for x in a)) ^ 76:11 WPS416 Found `yield` inside comprehension print(set((yield x + '!') for x in a))

            И давайте перепишем обработку, как нам предлагают.

            print()

            Эта задачка была сложна, но и мы не лыком шиты. Что же дальше?

            Злобный двойник email

            Если нужно записать адрес электронной почты, то используем строку, ведь так? А вот и нет!

            Для решения обычных задач существуют необычные способы. А у обычных типов данных есть злые двойники. Сейчас мы выясним, кто есть кто.

            class G: def __init__(self, s): self.s = s def __getattr__(self, t): return G(self.s + '.' + str(t)) def __rmatmul__(self, other): return other + '@' + self.s username, example = 'username', G('example') print(username@example.com) # => username@example.com

            Разберемся, как это работает.

            • в Python @ — это оператор, который можно переопределить с помощью магических методов __matmul__ и __rmatmul__ .
            • выражение .com означает обращение к свойству com ; переопределяется методом __getattr__ .

            Этот пример значительно отличается от остальных тем, что он-то на самом деле корректный. Просто вот такой необычный. Вероятно, пользоваться им мы не будем, но в бестиарий запишем.

            Сила заблуждений

            В нашем королевстве настали смутные времена. Тьма наделила жителей сомнительными способностями. Это раскололо содружество разработчиков и привело к серьезным разногласиям.

            Способности эти воистину страшные, ибо теперь вам дано программировать в строках:

            from math import radians for angle in range(360): print(f' ') print(th) # => angle=0 (th:=radians(angle))=0.000 # => 0.0 # => angle=1 (th:=radians(angle))=0.017 # => 0.017453292519943295 # => angle=2 (th:=radians(angle))=0.035 # => 0.03490658503988659

            Что происходит в этом примере?

            • f’ — это способ записи f’angle= в новых версиях (python3.8+).
            • (th:=radians(angle)) — это операция присваивания значения; да, теперь можно так делать и внутри строки.
            • =:.3f указывает на формат вывода: возвращается значение, округленное до третьего знака
            • метод print(th) отрабатывает, так как (th:=radians(angle)) имеет локальную область видимости в части кода, где находится вся строка.

            Стоит ли использовать f-строки? Как хотите.

            Стоит ли определять переменные в f-строках? Ни в коем случае.

            А вот дружеское напоминание о том, что еще можно (но, наверное, не нужно) написать с помощью f -строк:

            print(f"") # => posix

            Всего лишь импортируем модуль внутри строки, ничего такого, идем дальше.

            К счастью, в реальном коде наше оружие сразу почует неладное и засветится, аки знаменитый меч Жало:

             105:1 WPS221 Found line with high Jones Complexity: 16 print(f"") ^ 105:7 WPS305 Found `f` string print(f"") ^ 105:18 WPS421 Found wrong function call: __import__ print(f"") ^ 105:36 WPS349 Found redundant subscript slice print(f"") ^

            И еще кое-что: f -строки нельзя использовать как переменные docstrings :

            def main(): f"""My name is /!""" print(main().__doc__) # => None

            Заключение

            Мы сразились со многими жуткими монстрами, расплодившимися в коде, и сделали королевство Python прекраснее. Вы герой, гордитесь собой!

            Это было невероятное приключение. И я надеюсь, что вы узнали что-то новое для себя, что поможет в грядущих сражениях. Мир нуждается в вас!

            На сегодня все. Удачи на тракте, пусть звезды ярко освещают ваш путь!

            Полезные ссылки

            • Python code disasters
            • wtf, python?
            • wemake-python-styleguide

            А вы, вольные жители Python королевства, встречались с подобной черной магией в вашем коде? Удалось ли справиться с ней? Или битва еще не завершена (или вовсе проиграна)? Если вам нужна помощь бывалых магов и чародеев Python, то приходите к нам на Moscow Python Conf++ 27 марта 2020 года. У нас будут проверенные рецепты по борьбе с плохим и старым кодом от Владимира Филонова (доклад + 2 часа практики), Кирилла Борисова и Левона Авакяна.

            • python
            • open-source
            • wemake-python-styleguide
            • moscow python conf++
            • Блог компании Конференции Олега Бунина (Онтико)
            • Open source
            • Python
            • Программирование
            • Совершенный код

            Python: Магические числа

            Возьмем пример программы, которая считает курс валют:

            euros_count = 1000 dollars_count = euros_count * 1.25 # 1250.0 rubles_count = dollars_count * 60 # 75000.0 print(rubles_count) 

            С точки зрения профессиональной разработки, такой код не соответствует «лучшим практикам» — best practices.

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

            В нашем примере контекст легко восстановить, потому что переменные названы грамотно. Но в реальных проектах код значительно сложнее, поэтому догадаться до смысла чисел зачастую невозможно.

            Проблема кроется в «магических числах» — magic numbers. Это числа, происхождение которых невозможно понять с первого взгляда — приходится глубоко вникать в то, что происходит в коде.

            Чтобы предотвратить проблему, нужно создавать переменные с правильными именами. Так все встанет на свои места:

            dollars_per_euro = 1.25 rubles_per_dollar = 60 euros_count = 1000 dollars_count = euros_count * dollars_per_euro # 1250.0 rubles_count = dollars_count * rubles_per_dollar # 75000.0 print(rubles_count) 

            В этой программе:

            • Используется именование snake_case
            • Две новые переменные отделяются от последующих вычислений пустой строчкой. Эти переменные имеют смысл и без вычислений, поэтому такое отделение уместно, потому что повышает читаемость
            • Получился хорошо именованный и структурированный код, но он длиннее прошлой версии. Так часто бывает — это нормально, ведь код должен быть читабельным

            Магические числа и непонятные именования переменных не ломают код, но делают его менее читабельным.

            Нужно понимать, что компьютер в любом случае выполнит заданное вычисление. Однако другой программист будет читать код и ничего не поймет — это усложнит работу. Правильное именование переменных — половина успеха анализа кода.

            Задание

            Вы столкнулись с таким кодом, который выводит на экран общее количество комнат во владении нынешнего короля:

            king = "Rooms in King Balon's Castle:" print(king) print(6 * 17) 

            Как видите, это магические числа: непонятно, что такое 6 и что такое 17. Можно догадаться, если знать историю королевской семьи: каждый новый король получает в наследство все замки от предков и строит новый замок — точную копию родительского.

            Эта странная династия просто плодит одинаковые замки…

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

            Rooms in King Balon's Castle: 102

            Названия переменных должны передавать смысл чисел, но должны при этом оставаться достаточно короткими и ёмкими для комфортного чтения.

            Помните: код будет работать с любыми названиями, а наша система всегда проверяет только результат на экране, поэтому выполнение этого задания — под вашу ответственность.

            Упражнение не проходит проверку — что делать? ��

            Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

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

            В моей среде код работает, а здесь нет ��

            Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

            Мой код отличается от решения учителя ��

            Это нормально ��, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

            В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

            Прочитал урок — ничего не понятно ��

            Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

            Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

            Полезное

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *