Задать вопрос
Профиль пользователя заблокирован сроком с 21 сентября 2022 г. и навсегда по причине: Нарушение п.6.4, 6.6 Регламента. Накрутка, использование более одного аккаунта.
  • В чем заключаются архитектурные ошибки моего кода?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    class Calculation():
    
      def __init__(self, calculation):
        #init
        self.calculation = calculation

    Вы сделали класс `Вычисления`, чтобы проводить вычисления, пока проводятся вычисления вычислений над вычислениями, которые вычисляются как аргумент вычислений для вычисления состояния вычислений.

    Вы бы хотя бы в предметную область нас тут погрузили хоть немножечку. Не понятно же ничерта. Обычно класс и инстанс можно называть одинаково, за исключением первой буквы, но вы тут в аргументы что-то передаёте и то нифига не понятно. Делайте докстринги.

    Используйте тайпхинтинг, это позволяет не только статичесий анализ кода делать и избегать лишних ошибок, но, к тому же, это мощный инструмент документирования кода, неотрывно связанный с самим кодом. Это значит, что документация не отстанет от кода, а, напротив, будет за счет формализма и машиночитаемости помогать IDE помогать нам писать код. К тому же ряд вопросов отпадёт у тех, кто пытается читать код. Не нужно гадать на кофейной гуще что есть что.

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

    У вас в коде полно "магических" констант. Именуйте их и выносите в начало модуля или, хотя бы, указывайте в инлайн-комментах единицы измерения для ясности. Не пренебрегайте свойствами, их можно документировать .

    Вы тут много работаете с календарными периодами. перебираете их с шагом... Это хорошее место для выделения функциональности в отдельную библиотеку, в отдельный тип данных. Возможно писать свой велосипед даже не придётся, ведь найдётся много готовых качественных протестированных библиотека для этих целей. Их будет легко и понятно инициализировать, у них будет простой, понятный и универсальный АПИ, они будут однотипно использованы в разных мемтах проекта, не придётся смешивать в одном контесте кучу переменных для обеспечения двух имплементаций одной и той же функциональности.
    Количество кода резко убавится, универсальный код будет вынесен в отдельный модуль и будет отдельно и полноценно протестирован, а в бизнес логике вы будете коротко и лаконично работать с абстракцией - понятной и простой.

    Вот тут у вас, очевидно, можно написать проще и без лишних повторений, провоцирующих ошибки:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i not in range(0, self.inflation_indexation_period):
              init_indexation_inflation *= self.sales_init.inflation_indexation
            else:
              init_indexation_inflation = 1
            inflation_indexations.append(round(init_indexation_inflation, 5))
          else:
            inflation_indexations.append(round(init_indexation_inflation, 5))

    Лучше так:
    if i % self.inflation_indexation_period==0 and i != 0:
            if i in range(self.inflation_indexation_period):
              init_indexation_inflation = 1
            else:
              init_indexation_inflation *= self.sales_init.inflation_indexation
    
          inflation_indexations.append(round(init_indexation_inflation, 5))

    Функция get_inflation_indexations у вас имеет опасный побочный эффект. Она имеет префикс get_ но модифицирует контекст объекта. Это кэширование? Чем обусловлено такое поведение? Если такое делается "на всякий случай". то это плохая практика неявного внедрения побочного эффекта. Если нарочно, то такое надо документировать и корректно называть и описывать метод в докстринге.

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

    Перестаньте использовать i в качестве переменной для итерирования нетривиальных сущностей, отличных от протсого счетчика. i - это индекс. Используйте человеко-понятное название переменной для этого!

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

    А вот здесь вообще всё плохо:
    count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1

    count - это "количество", а вы его используете как "индекс" и никак иначе!
    i - это индекс, а вы туда суёте фактически цену!
    У вас total_price и total_value параллельные одноразмерные списки, их нужно состегнуть с помощью zip и пронумеровать с помощью enumerate (если надо, а здесь не надо!).
    Весь этот кусок понятнее, проще, короче и более питоничнее записать в такой форме:
    revenue_list = [price * value for price, value in zip(total_prices, total_values)]


    Итого вся вот эта громоздкая плохо читабельная функция:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        total_price = []
        for i in self.get_inflation_indexations():
          price = self.sales_init.price*i
          total_price.append(price)
    
        total_value = []
        for i in self.get_value_indexations():
          value = self.sales_init.sales_volume*i
          total_value.append(value)
    
        count = 0
        revenue_list = []
        for i in total_price:
          revenue = i*total_value[count]
          revenue_list.append(revenue)
          count+=1
    
        return revenue_list

    Легко и читабельно для питониста заменяется на вот такую:
    def get_revenue(self):
        '''Получить итоговую выручку'''
        indexations = self.get_inflation_indexations()
    
        init_price = self.sales_init.price
        total_prices = [init_price * x for x in indexations]
    
        init_volume = self.sales_init.volume
        total_values = [init_volume * x for x in indexations]
    
        return [price * value for price, value in zip(total_prices, total_values)]


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

    Что это за ерунда:
    def get_interest_expenses(self):
        '''процентные расходы'''
        interest_expenses_list = []
        return interest_expenses_list


    Зачем много раз считать одно и то же целиком, чтобы взять только очередной кусочек из всего посчитанного?!
    Это вообще бред. Учитесь основам алгоритмизации и не надо программировать на питоне как не на питоне.

    Вот такое вообще жесть: self.get_revenue()[count]
    Отчего не сохранить в промежуточную переменную?!

    В общем, всё плохо.
    Если у вас есть функция, вычисляющая какой-то список, то зачем её вычислять каждый раз, когда вам нужен только один очередной элеиент этого списка, а вы перебираете его целиком?!
    И так много раз везде!
    Тут не архитектура хромает, тут основы алгоритмизации плачут. Тренируйтесь на кошках, сударь, больше решайте алгоритмических задачек. Структурируйте, декомпозируйте.

    Удачи.
    Ответ написан
    3 комментария
  • Чем тег figcaption отличается от атрибута alt?

    Атрибут alt - это альтернативное описание. Например, когда не удается подгрузить картинку, то на странице будет отображаться текст из alt. Используется для тега img, но может также присутствовать в area и input (если тип вода изображение).
    figcaption - это описание к элементу. Используется в тегах для изображений, видео, диаграмм и т.д. Отображается на странице всегда. Если взять книгу для примера, то это описание под иллюстрацией.
    Если вы заполните оба атрибута, и картинка по какой-то причине не загрузиться, то вы увидите на странице и то, что содержится в alt, и то, что написано в figcaption.

    https://thoughtbot.com/blog/alt-vs-figcaption
    Ответ написан
    Комментировать
  • Не открывается сайт в браузере хром?

    @Drno
    Потому что моззила открывает через свои DNS,..
    А хром через те, которые у ПК указаны. Поэтому скорее всего еще не обновились DNS записи у того ДНСа, которым вы на ПК пользуетесь
    Ответ написан
    2 комментария
  • Почему ozon не отдает страницу?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    перестарался с хидерами

    Постманом проходишь? отдает?
    Ответ написан
    2 комментария
  • Смогут ли меня вычислить в vk и привлечь к ответственности, если я сделаю эти действия?

    CityCat4
    @CityCat4 Куратор тега Информационная безопасность
    //COPY01 EXEC PGM=IEBGENER
    Чувак, ты либо мой коллега-тролль, либо просто "молодец" (в одной из прежних контор это слово у нас было аналогом слова "долб..б"). Тебя уже нашли и это вовсе не шутка :)
    1. Покупаю чужую страницу в vk

    ...и нарушаю правила vk, который тут же эту страницу забанит. Про то, что он сольет логи и все что запросят - даже и не говорю - предполагается по умолчанию.
    3. Ставлю VPN, который не надо оплачивать

    ...и натыкаюсь на VPN, который сливает логи российским спецслужбам. Отличное решение. Да, нельзя точно сказать, что он сливает именно им, нельзя даже точно сказать, что вообще сливает. Но предполагать надо самое худщее. Любой VPN сливает логи, вопрос только в том, кому.
    Но разве правоохранительные органы смогут понять, какую именно я страницу купил?

    Еще как смогут. ВК в этом им будет активно помогать. На самом деле образ тупого опера - это киношный штамп, который намеренно не развенчивается, а реально - там в достатке и умений и знаний :)
    Смогут ли меня привлечь к ответственности за несанкционированный доступ к чужой странице?

    Когда зайдет речь о том, будет ли это УК 137 или же УК 207.3 Вы сами сдадите все свои VPN, прокси, торы и прочее что там у Вас будет - лишь бы не попасть под УК 207.3

    Подумайте - а стоит ли оно того? Есть тьма других площадок, чтобы высказать свое мнение, в том числе и таких, на которых особо и стесняться не надо - правда в РФ они забокированы :)
    Ответ написан
    Комментировать
  • Нашел приватный мессенджер Prival, стоит ли пользоваться, надежен ли?

    @Sergei7774
    Автор темы прав. Эти серверные мессенджеры, которые заполонили интернет все читаются (вышел закон) и нужно от них уходить. Сам сижу на бессерверных Bitmessage и Тox
    Упоротые и страшные, как черти, но куда надёжнее чем обычная почта. К стати мою почту уже ломали, последний раз пароль украли. Ушёл от темы. Prival этот посмотрел сайт. Очень забавный сайт, сказать ничего не могу про ЭТО
    На мой взгляд хороший мессенджер Bitmessage хотя очень страшен и неудобен. Это смесь бульдога с носорогом, то есть почты как в программном виде. Имён там нет одни какие-то цифры, вобщем ни о чём. Тяжела работа хакера ))
    Ответ написан
    Комментировать
  • Покупка мака на М1 - это было невменяемым решением?

    @Drno
    Железка не виновата что юзер не может...

    Потому что Intel Это x86 процессор, а m1 это ARM...
    Как посоветовали в комменте - установи rosetta и всё заработает как обычно...
    Ответ написан
    1 комментарий
  • Восстанавливает данные мошенник?

    CityCat4
    @CityCat4
    //COPY01 EXEC PGM=IEBGENER
    Написать в спортлото, скорее всего, как Высоцкий советовал :) Если есть договор на оказание услуг - можно и в полицию. Если договора нет и факт передачи денег никак никем не подтверждается - только в спортлото и винить себя в желании сэкономить на такой вещи как восстановление данных.

    Кроилово ведет к попадалову
    Ответ написан
    7 комментариев
  • Выполнение скрипта в определенном разделе на странице сайта?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Либо по старинке отслеживать событие scroll и вычислять положение нужного блока на экране, либо использовать Intersection Observer и смотреть момент пересечения нужного блока с вьюпортом.
    Ответ написан
    Комментировать
  • Mikrotik перестал "будить компы" через WakeOnLan после перезагрузки, как решить проблему?

    @Zzzz9
    Нужно вычислить в чем проблема, в микроте или компе, можно поставить посередине прослушку, проанализировать трафик, если волшебный пакет проходит- проблема в компе, если волшебного пакета нет- виноват микрот или доп устройства если есть.
    Ответ написан
    4 комментария
  • Как сменить приоритет использования стиля для кнопки?

    delphinpro
    @delphinpro Куратор тега CSS
    frontend developer
    Для понимания вопроса загуглите тему про специфичность селекторов и каскадность стилевых таблиц.
    В общем случае, вы почти ничего не можете сделать, потому что у вас нет возможности изменить сторонний код.
    Но вы можете переписать свои стили так, чтобы они не влияли на кнопку.

    Например в данном коде есть следующие селекторы

    button {}
    [type="button"] {}
    .SIZE_5 {}
    button[type="button"] {}
    button.SIZE_5 {}


    Вы можете убрать из своих css файлов эти селекторы
    Ответ написан
    1 комментарий
  • Какая минимальная мощность VPS для развертывания OpenVPN?

    @Drno
    От 512рам и 5гб диск
    Про безопастность - это бред)
    Ответ написан
    8 комментариев
  • Какая минимальная мощность VPS для развертывания OpenVPN?

    @rPman
    размещение 'центра сертификации' отдельно от сервера openvpn не повысит безопасность ни в каком смысле, центр сертификатов это просто набор утилит и файловое хранилище, к которому openvpn должен иметь доступ на запись, имея доступ к ключам хотя бы на чтение можно делать что угодно (например подключаться под любым пользователем и делать mitm)

    Требования по openvpn очень маленькие, считанные десятки мегабайт ram и мегабайты на диске, так что бери любой vps, но openvpn (как и любой другой vpn сервер но конкретно этот самый жрущий) очень требователен по процессору, если тебе нужен мегабит, тебе хватит любой слабой машины, но если ты хочешь сотни мегабит, то тебе понадобится топовый процессор (и он не распаралеливает нагрузку по ядрам)
    Ответ написан
    3 комментария
  • Как отключить скролл колеcиком мышки для всего body?

    ev_g
    @ev_g
    Web dev.
    body {
        overflow: hidden;
    }


    Но возможно потребуются дополнительные стили, вроде height: 100vh, но для этого нужно смотреть всю логику работы приложения.
    Ответ написан
    Комментировать
  • Почему в google analitics нет валюты белорусского рубля, BYN?

    neuotq
    @neuotq
    Прокрастинация
    Вопрос конечно немного посмешил, боюсь и рубль РФ уже скоро оттуда пропадет.
    А если без шуток, то просто не вошел в ограниченный список поддерживаемых локальных валют.
    Вот он:
    https://support.google.com/analytics/answer/620590...
    Ответ написан
    4 комментария
  • При нажатии на кнопку нужно сделать переход на другую страницу на PHP?

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    да занефиг:
    <?php 
    echo '<a href="/gobuhati" class="button beer-button-blue">Пивка?</a>';
    ?>
    Ответ написан
    Комментировать
  • Как удалить лишние файлы в linux?

    xotkot
    @xotkot
    хорошо есть и хорошо весьма
    создадим тестовую площадку:
    mkdir -p /tmp/TEST && touch "/tmp/TEST/backup-name-back-"{01..05}"-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-"{10..13}-{100..104}".bak" && tree /tmp/TEST

    вывод tree
    /tmp/TEST
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-100.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-101.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-102.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-103.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-104.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-11-100.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-11-101.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-11-102.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-11-103.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-11-104.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-12-100.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-12-101.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-12-102.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-12-103.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-12-104.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-100.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-101.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-102.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-103.bak
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    ├── backup-name-back-02-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-10-100.bak
    ...
    ├── backup-name-back-05-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-102.bak
    ├── backup-name-back-05-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-103.bak
    └── backup-name-back-05-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    
    0 directories, 100 files

    получим 100 файлов бэкапа

    теперь несколько однострочников
    прописываем полный путь к папке где хранятся бэкапы и заодно закинем список для сравнения в переменную Т
    DIR="/tmp/TEST"; T=$(ls $DIR/* |awk -F'[-.]' '{print $4" "$(NF-2)$(NF-1)";"$0}')

    показать что останется после удаления
    echo "$T" |sort -nr |sort -un |awk -F';' '{print $2}'

    показать что удалиться
    comm -3 <(echo "$T" |sort -n) <(echo "$T" |sort -nr |sort -un) |awk -F';' '{print $2}'

    !!! удаляем !!!
    rm $(comm -3 <(echo "$T" |sort -n) <(echo "$T" |sort -nr |sort -un) |awk -F';' '{print $2}')

    по итогу получим:
    $ tree /tmp/TEST
    /tmp/TEST
    ├── backup-name-back-01-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    ├── backup-name-back-02-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    ├── backup-name-back-03-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    ├── backup-name-back-04-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    └── backup-name-back-05-название_на_русском,_могут,_встречаться_(скобки,_точки,_запятые.)-13-104.bak
    
    0 directories, 5 files
    Ответ написан
    1 комментарий
  • Как сделать чтобы команда выполнялась при запуске?

    paran0id
    @paran0id Куратор тега Linux
    Умный, но ленивый
    Гляньте утилиту iptables-persistent - она сохраняет правила iptables и применяет их после перезагрузки.

    Можно также сделать systemd service (type oneshot), выполняющий эту команду.
    Ответ написан
    Комментировать
  • Как сохранять данные при перезагрузке страницы?

    @BUTURUM
    Самым грамотным решением в данном случае было бы хранить все данные на сервере, а клиенту отдавать id сессии в cookie, по которому и предоставлять необходимые данные. Если говорить про реализацию полностью на фронте, то почитайте эту статью
    Ответ написан
    Комментировать
  • Что не так, библиотека telebot?

    @jikrdev
    Дело в том, что Вы указали переменную call, вместо message и получается так, что Вы пытаетесь вызвать несуществующию переменную. Есть два решения, одно из них:

    @bot.callback_query_handler(func = lambda call: True)
    def movie_choice(message):
      if message.data=='shameless':
        markup2=types.InlineKeyboardMarkup(row_width=1)
        s1 = types.InlineKeyboardButton("1 сезон", callback_data = 's1')
        s2 = types.InlineKeyboardButton("2 сезон", callback_data = 's2')
        s3 = types.InlineKeyboardButton("3 сезон", callback_data = 's3')
        s4 = types.InlineKeyboardButton("4 сезон", callback_data = 's4')
        s5 = types.InlineKeyboardButton("5 сезон", callback_data = 's5')
        markup2.add(s1,s2,s3,s4,s5)
        bot.send_message(message.chat.id, 'Выбери сезон, который хочешь посмотреть:', reply_markup = markup2)
    Ответ написан
    Комментировать