Задать вопрос
  • Как изменить клавиатуру на другую?

    Vindicar
    @Vindicar
    RTFM!
    Клавиатура обычно прикреплена к сообщению. Для её смены проще всего отправить поясняющее сообщение с новой клавиатурой.
    Ответ написан
    Комментировать
  • Как проверить количество цифер после точки во float в Python?

    Vindicar
    @Vindicar
    RTFM!
    Число цифр - штука коварная. Вот беру я Питон и вбиваю:
    >>> 0.1 + 0.2
    0.30000000000000004

    Сколько цифр должен вывести код?
    Ответ написан
    Комментировать
  • Насколько такой метод проверки является корректным и как его можно сократить?

    Vindicar
    @Vindicar
    RTFM!
    1. Не надо проверять в рантайме type(m) == int. Достаточно указать в заголовке функции
    def add_time(self, h: int = 0, m: int = 0, d: int = 0, dw: int = 0, mh: int = 0, y: int = 0):

    Этого будет достаточно, чтобы IDE/статический анализатор сказал программисту "эй, ты фигню передаёшь в этот метод". Да, это не будет контролироваться во время выполнения, но тут уже другой вопрос: если клиент-программист сделал класс, неотличимый от int, стоит ему позволить этот класс передать вместо int. Ответственность будет на нём.

    2. Ну для конкретно твоей проверки по значению можно просто:
    if any(v < 0 for v in [h,m,d,dw,mh,y]):
        raise ValueError()

    Если хочешь красиво, можно и выпендриться:
    args = {'h':h, 'm':m, 'd':d, 'dw':dw, 'mh':mh, 'y':y}
    bad = list(filter(lambda k: args[k] < 0, args.keys()))
    if bad:
        raise ValueError('Invalid values for: ' + ','.join(bad))


    Ну а при большом желании можно и целый велосипед для декларативной проверки параметров замутить.
    Но смысл?
    import functools
    import inspect
    
    # пусть чек-функция имеет вид (value) -> bool, и возвращает True для "хороших" значений. Пример:
    def not_whitespace(s: str) -> bool:
        'String must not contain only whitespace'  # док строка будет использоваться в сообщении об ошибке
        return bool(s.strip())  # проверяем что строка не состоит из одних пробелов.
    # чек-функции можно генерировать и на ходу:
    def in_range(low, high):
        def check(value):
            return (low is None or low <= value) and (high is None or value <= high)
        check.__doc__ = f'Value must be between {low} and {high}.'
        return check
    # теперь сделаем декоратор, который умеет принимать чек-функции и применять их перед вызовом цели
    def check(**checks):
        def wrapper(func):
            sign = inspect.signature(func)
            names = list(sign.parameters.keys())  # имена параметров по порядку
            not_found = set(checks.keys()) - set(names)  # все ли чеки ссылаются на известные параметры?
            if not_found:
                # у нас есть чек на неизвестный параметр!
                raise NameError(', '.join(not_found))
            # всё ок, делаем обёртку над функцией
            
            @functools.wraps(func)
            def wrapped(*args, **kwargs):
                bad = []
                for param_name, check_func in checks.items():
                    idx = names.index(param_name)
                    if idx < len(args):
                        # параметр был передан через args
                        value = args[idx]
                        if not check_func(value):  # вызываем чек-функцию
                            err = getattr(check_func, '__doc__', '')
                            if err:
                                bad.append(f'{param_name} ({err})')
                            else:
                                bad.append(param_name)
                    else:
                        pass  # могут быть хитрости с kwargs-only параметрами. Тут уж извини, мне влом писать.
                if bad:  # нашли ошибки?
                    raise ValueError('Bad value for parameters: '+', '.join(bad))
                    # тут ещё можно помудрить над скрытием последнего фрейма в traceback, но мне опять влом
                else:  # не нашли, вызываем функцию
                    return func(*args, **kwargs)
            
            return wrapped
        return wrapper
    
    # пример использования
    # строка должна быть не из одних пробелов
    # число должно быть в пределах от 1 до 10 включительно
    @check(s=not_whitespace, n=in_range(1, 10))
    def repeat(s: str, n: int) -> str:
        return s * n
    
    print(repeat('test ', 3))
    
    try:
        print(repeat('test ', 20))
    except ValueError as err:
        print('yep! it failed!', err)
    
    try:
        print(repeat('test ', -1))
    except ValueError as err:
        print('yep! it failed!', err)
    
    try:
        print(repeat('    ', 5))
    except ValueError as err:
        print('yep! it failed!', err)
    
    try:
        print(repeat('    ', 15))
    except ValueError as err:
        print('yep! it failed!', err)
    Ответ написан
    3 комментария
  • Как получить все 3 канала изображения?

    Vindicar
    @Vindicar
    RTFM!
    По умолчанию каналы изображения в opencv идут в порядке blue, green, red.
    Так что 0 - это blue, ну и так далее.
    Ответ написан
  • Бот перестаёт отвечать после возврата в главное меню, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    button1 = types.KeyboardButton(" Поздороваться")
    button2 = types.KeyboardButton("❓ Задать вопрос")

    Сравни это с реализацией команды /start. У тебя тут посторонние пробелы, а сравнение строк требует ТОЧНОГО совпадения. В твоём коде - вплоть до регистра букв.
    Ответ написан
    Комментировать
  • Как корректно выводить таблицу в телеграм?

    Vindicar
    @Vindicar
    RTFM!
    tabulate рассчитана на использование моноширинного шрифта, как в терминале. С таким шрифтом можно подравнивать строки пробелами из расчёт 1 пробел на символ.
    Клиенты телеги, как и 99% приложений, используют по умолчанию пропорциональный шрифт. Там такой фокус не проходит.
    1920px-Propvsmono.svg.png
    Попробуй завернуть выводимую таблицу в ```три бэктика```, это markdown для использования моноширинного шрифта.
    Ответ написан
    Комментировать
  • Как понять работу следующего кода по перегрузке операторов?

    Vindicar
    @Vindicar
    RTFM!
    Потому что питон пытается "извернуться", если описаны не все операторы.
    Если выполняется a < b, но не описан оператор a.__lt__(), питон попробует вызвать b.__gt__().
    Аналогично, если не описан __ne__() а только __eq__(), и выполняется a != b, питон сделает not (a == b)
    Кое что есть тут
    Также советую глянуть в сторону functools.total_ordering.
    Ответ написан
    3 комментария
  • В чем ошибка у discord.py и socket?

    Vindicar
    @Vindicar
    RTFM!
    Лови исключения. И привыкай к мысли что любая сетевая операция (да что там, любой ввод-вывод) может завершиться с ошибкой.

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

    Vindicar
    @Vindicar
    RTFM!
    Для обучения основам составления алгоритмов сойдёт. Больше, считай, ни для чего.
    Ответ написан
    Комментировать
  • Как сделать что б while работал пока может?

    Vindicar
    @Vindicar
    RTFM!
    Выяснить, почему он зацикливается, и исправить.
    Обходные варианты существуют, но они привносят куда больше проблем, чем решают.
    Ответ написан
    Комментировать
  • Почему не происходит отправка сообщений ботом в установленное время?

    Vindicar
    @Vindicar
    RTFM!
    if current_time == '12:00':
    У тебя значение current_time определяется один раз, ДО цикла. Ты ожидаешь, что оно волшебным образом будет следовать за текущим временем?
    Ответ написан
    Комментировать
  • TelegramBot + SQLite?

    Vindicar
    @Vindicar
    RTFM!
    Ну технически возможно: sqlite позволяет описывать user defined functions, которые можно вызывать внутри SQL-запросов - в том числе внутри триггеров. Вот только большой вопрос, что это за функции. С асинхронщиной могут быть проблемы.

    Но честно, я бы лучше сделал простой поллинг. Запросил все записи позднее заданного времени, если такие записи есть - обработал, заменил заданное время на самое позднее из этих записей. Повторять раз в пять минут.
    Да, время реакции медленнее, но зато код куда понятнее, и проще портируется на другую БД, если что.
    Ответ написан
    3 комментария
  • Почему проходят первые тесты, но не проходят вторые на Codewars?

    Vindicar
    @Vindicar
    RTFM!
    Тормозит, потому что ты брутфорсишь перебор простых чисел. Используй решето Эратосфена.
    Иными словами, тебе не нужно перебирать все числа меньшие N, чтобы найти делители - достаточно проверить все простые числа, меньшие или равные N/2. А так как ты находишь простые числа по возрастанию, то все эти числа ты уже знаешь.
    До кучи, 2 всегда простое, а вот другие чётные числа - нет. Можешь добавить 2 в список заранее, а цикл по i делать от 3 с шагом 2.

    Ну и да, не называй переменную list. Это сбивает с толку.
    Ответ написан
    Комментировать
  • Как из текстового файла достать строки в определённом диапазоне?

    Vindicar
    @Vindicar
    RTFM!
    Пропустить нужное число строк, прочитать нужное число строк.
    def read_lines_in_range(f, ifrom: int, ito: int) -> list[str]:
        f.seek(0)
        for i in range(ifrom):
            f.readline()
        return [f.readline() for i in range(ito-ifrom)]

    Единственное, позиция чтения в файле должна быть в начале файла. Так что файл надо либо закрыть и открыть, либо сделать f.seek(0).
    Ответ написан
    Комментировать
  • Как найти ближайшее меньшее к моему числу из заданных чисел?

    Vindicar
    @Vindicar
    RTFM!
    Так как у тебя степени двойки, то можно рассчитать математически.
    import math 
    z = float(input('Z = '))  # например, 10
    logz = math.log(z, 2)  # 10 находится между 2**3 и 2**4, так что logz будет 3 с копейками (но меньше 4)
    pwr = int(logz)  # отбрасываем дробную часть, получаем 3
    value = 2 ** pwr  # ближайшее меньшее значение - 2 ** 3

    Но для произвольных чисел это не сработает.
    Ответ написан
    Комментировать
  • Как сделать так, чтобы бот отвечал на команду start?

    Vindicar
    @Vindicar
    RTFM!
    Что за @bot.send_message? Здесь декоратору не место, тут нужен просто вызов функции.
    Ответ написан
    7 комментариев
  • Как распарсить строку (python)?

    Vindicar
    @Vindicar
    RTFM!
    shlex.split(), например?
    Ответ написан
    Комментировать
  • Как скачать музыку с Vk с помощю Python?

    Vindicar
    @Vindicar
    RTFM!
    youtube-dl?
    Оно не только YouTube умеет, а ещё много какие сайты. Есть командная строка, вроде был и питоновский интерфейс. Хотя можно тупо через subprocess запустить.
    Ответ написан
    Комментировать
  • Как убрать двойные кавычки при чтении CSV файла?

    Vindicar
    @Vindicar
    RTFM!
    Читаем доку.
    quoting: optional constant from csv module
    Defaults to csv.QUOTE_MINIMAL. If you have set a float_format then floats are converted to strings and thus csv.QUOTE_NONNUMERIC will treat them as non-numeric.

    Константы, которые можно использовать для контроля кавычек, описаны в доках на csv.
    Тот же параметр quoting есть и у read_csv()
    Ответ написан
    Комментировать
  • Как записать файл в папке?

    Vindicar
    @Vindicar
    RTFM!
    Ну тебе тут и насоветовали... Читай что такое относительный и абсолютный пути.
    C:\папка\user_file - это абсолютный путь.
    \папка\user_file - это относительный путь от корня текущего диска.
    папка\user_file - это относительный путь от текущей директории.
    Текущая директория (равно как и диск) может быть разной при запуске скрипта, может быть изменена в ходе работы скрипта, и не обязательно совпадает с директорией скрипта.
    Если тебя это устраивает, например, если ты пишешь программу для командной строки, которая принимает путь как параметр - то можешь использовать относительный путь.
    Если же ты хочешь обратиться к какому-то файлу с данными в каталоге скрипта - лучше сконструировать абсолютный путь. Не указать его явно (тогда придётся менять при перемещении скрипта в другую папку), а сконструировать. Например, так:
    import pathlib  # стандартный модуль питона. Очень советую его освоить!
    import sys
    # путь к папке скрипта, например, C:\myscript
    script_dir = pathlib.Path(sys.argv[0]).parent  
    # путь к файлу собирается из частей вот так
    user_file = script_dir / "some_folder" / "user_file"  # C:\myscript\some_folder\user_file
    # обрати внимание, мы не паримся по поводу того, что 
    # под виндой разделитель каталогов \, а под линуксом /
    # это уже забота pathlib
    with user_file.open('w+') as f:
        pass  # делаешь что тебе нужно с файлом
    # через функцию open() тоже сработает, метод open() просто для удобства
    with open(user_file, 'w+') as f:
        pass  # делаешь что тебе нужно с файлом

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