Еще в июне Basencode начинался как хобби-проект моего друга (проверьте его). Он хотел создать программное обеспечение, которое могло бы легко преобразовывать числа между основаниями. На такую ​​функцию есть большой спрос, как показано в этом вопросе Переполнение стека, который в настоящее время имеет поразительные 347 000 просмотров, в среднем 75 просмотров каждый день. На этот вопрос было 34 ответа (до того, как я опубликовал свой), и этот вопрос был отмечен платформой как высокоактивный вопрос.

Удивительно, однако, что ни один ответ из 34 (я тогда не проверял их все, но, судя по верхним) не дал универсального решения. Многие из ответов определяли несколько заумные функции вместо того, чтобы предлагать библиотеки Python, решающие проблему, и большинство библиотек, которые поддерживали эту функцию, были ограничены — Numpy поддерживал только базы до 36, а Gmpy2 не тестировался в последних обновлениях.

Ответ, получивший наибольшее количество голосов, также определил функцию, которая поддерживала все базы до бесконечности. Однако, используя этот ответ, числа с плавающей запятой нельзя было преобразовать, а пользовательские цифры нельзя было настроить.

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

Версия 1.0.0 была выпущена на PyPI в начале июня, но в ней были ошибки, несоответствия и задачи. Например, базы от 2 до 36 поддерживались встроенно, и база 64 тоже поддерживалась, а от 37 до 63 — нет.

Итак, 29 октября мы добавили встроенную поддержку для всех баз, а также резко сократили кодовую базу почти на 40%, используя лучший дизайн и итерационные стратегии. Однако мы все еще не добавили такие функции, как преобразование чисел с плавающей запятой.

Версия 2

Затем мы приступили к еще большему сокращению и очистке кодовой базы, используя декораторы Python, строго придерживаясь DRY. Затем мы переименовали класс Integer в Number, исходя из (ошибочного) предположения, что целое число означает основание 10. Однако позже мы изменили этот бит.

Мы использовали Pytest для реализации автоматизированного тестирования. Улучшена документация, а стиль кода стал более согласованным и соответствующим соглашениям PEP 8. Чтобы повысить совместимость BasencodeIntegers и Python ints, мы добавили поддержку дополнительных функций int, таких как __rshift__, и удостоверились, что вы можете выполнять операции с Integer и int, например:

>>> Integer(2) + 2
Integer(4)

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

Когда закончился первый день ноября, нам удалось: а) поддержать преобразование float с помощью класса Basencode Float и б) позволить пользователю выбирать, в каком «режиме» будет представляться число. Например, в приведенном ниже фрагмент (который я скопировал из своего ответа на вопрос о переполнении стека), пользователь просит вернуть представление в виде list («l») вместо стандартного str («s»). Как видите, мы предоставляем цифры для этой базы, так как она больше 64 — поэтому, хотя некоторые утверждают, что это не «поддержка произвольно больших баз из коробки», я бы сказал, что этого достаточно, так как теперь пользователь может выбирать цифры в представлении своего числа.

>>> n1 = Number(67854 ** 15 - 102)
>>> n1.repr_in_base(577, digits=[str(i) for i in range(577)], mode="l")
['4', '473', '131', '96', '431', '285', '524', '486', '28', '23', '16', '82', '292', '538', '149', '25', '41', '483', '100', '517', '131', '28', '0', '435', '197', '264', '455']

Переопределение встроенных цифр было функцией, поддерживаемой в самом Basencode v1:

>>> n1.repr_in_base(2)
'1101011110011000110110001011000010110100010101100110001000110010100010111000100100011011011000100111110101001111001010100101110101011110100111101110001100110101100010100110001100010100100001010001100101011110010011111110110110111111110011010'
>>> n1.repr_in_base(2, list('-+'))
'++-+-++++--++---++-++---+-++----+-++-+---+-+-++--++---+---++--+-+---+-+++---+--+---++-++-++---+--+++++-+-+--++++--+-+-+--+-+++-+-+-++++-+--++++-+++---++--++-+-++---+-+--++---++---+-+--+----+-+---++--+-+-++++--+--+++++++-++-++-++++++++--++-+-'

После всего этого мы выпустили 2.0.0.

v2.1

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

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

Затем мы изменили наш класс Float, чтобы использовать decimal.Decimal вместо встроенных в Python floats. С помощью друга мы начали использовать GitHub Actions для автоматизации нашего рабочего процесса. Даже если мы забудем запустить Pytest, GitHub Actions проверит его за нас. И мы иногда ломали вещи.

Как видно на фотографии выше, мы тогда сосредоточились на улучшении документации — сначала в README, а затем в ReadTheDocs. У нас еще есть много возможностей для добавления, и я надеюсь, что вы найдете библиотеку полезной!