Задать вопрос
  • Считывание ключа домофона через NFC?

    Vindicar
    @Vindicar
    RTFM!
    Бесконтактные ключи работают на 125 kHz RFID-метках, а не на NFC.
    Ответ написан
    2 комментария
  • Как составить число n из элементов списка?

    Vindicar
    @Vindicar
    RTFM!
    Я бы решал задачу рекурсивно.
    Найди в списке все числа x, меньшие или равные n, определи их позиции в списке, отсортируй по убыванию числа.
    Если в списке есть x, равное n, ответ найден.
    Иначе перебирай числа по порядку, от больших к меньшим, и для каждого числа x пробуй убрать его из списка, а потом рекурсивно решить задачу для суммы n-x.
    Т.е. что-то типа:
    def compose_sum(numbers: list[int], total: int) -> list[int] | None:
        # ищем индексы потенциальных слагаемых
        indices = [i for i in range(len(numbers)) if numbers[i] <= total] 
        # сортируем по убыванию слагаемых, потом по порядку в списке
        indices.sort(key = lambda i: (numbers[i], i), reverse=True)
        # если нулевой элемент совпадает - мы нашли точную сумму. Прерываем рекурсию.
        if numbers[indices[0]] == total: 
            return [indices[0]]
        for index in indices: # иначе перебираем слагаемые
            numcopy = numbers.copy()
            # копия списка без рассматриваемого слагаемого
            current = numpcopy.pop(index)
            next_indices = compose_sum(numcopy, total - current)
            if next_indices:  # нашли решение, корректируем индексы (так как мы удалили один элемент)
                for i in range(len(next_indices)):
                    if next_indices[i] >= index:
                        next_indices[i] += 1
                return [index] + next_indices # отдаём наше решение "наверх"
            # next_indices пуст/None - решения не нашли, пробуем другой index
        return None # не нашли решения ни для одного index
    Ответ написан
    Комментировать
  • Почему выводит не совсем правильно?

    Vindicar
    @Vindicar
    RTFM!
    Ты забыл последнюю сторону многоугольника.
    p += len_seg(x[-1],y[-1],x[0],y[0])
    Ответ написан
    Комментировать
  • Как реализовать код диаграммы uml с стрелками зависимости и ассоциации?

    Vindicar
    @Vindicar
    RTFM!
    линия и пунктир с треугольной стрелкой самые понятные, они просто наследуют классы

    Неверно. Сплошная стрелка - да, наследует классы. Пунктир - это реализация интерфейса (в терминах Питона это скорее typing.Protocol). Т.е. при реализации один участник (с меткой interface) описывает методы без их реализации, а второй - их реализует.

    линии с ромбиками понятны отчасти, в свойстве класса создают экземпляр другого класса

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

    Зависимость - это когда один объект использует другой (имеет ссылку на другой), но в то же время их экземпляры не сопоставлены, т.е. связь между ними не имеет особого смысла с точки зрения решаемой задачи.
    Пример: окно, где показывается чат, и сам чат. Окно знает, какой чат оно показывает. В то же время одно окно может использоваться для разных чатов в разное время. Аналогично, один чат может показываться в разных окнах. Т.е. связь окно-чат не имеет какого-то особенного смысла. Сравни это со связью сообщение-автор.
    Ответ написан
  • Как импортировать с файла функцию, но чтобы этот файл не запускался?

    Vindicar
    @Vindicar
    RTFM!
    Заверни тело файла (непосредственный вызов функций) в конструкцию
    if __name__ == '__main__':
    Этот if выполнится, только если файл запущен непосредственно, и не выполнится, если он импортирован.
    Ответ написан
    Комментировать
  • Как получить колонку по ее значение?

    Vindicar
    @Vindicar
    RTFM!
    Короче.
    Основную идею я тебе дам, но всё равно почитай уже любой учебник!

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

    "А что делать, если у меня переменный набор данных? Например, есть чаты, и в них есть юзеры?"
    У тебя несколько сущностей - в таких случаях тебе нужно несколько таблиц. Ключевой момент - сколько сущностей связано с той или иной сущностью.
    Например, у нас есть чаты, и есть пользователи. Пользователь может быть в нескольких чатах, чат может иметь нескольких пользователей. Это называется "связь многие-ко-многим". Если сделать так, как ты делаешь сейчас, то будет таблица Чаты, и при добавлении пользователя в чат будет добавляться столбец в таблицу. Это неправильно!
    Правильно: есть таблица Чаты (каждый чат имеет свой id - "ключ", "primary key"), таблица Пользователи (каждый имеет свой ключ) и вспомогательная таблица (association table) ПользовательВЧате.
    В виде SQL это будет выглядить примерно так:
    CREATE TABLE Chats (id INTEGER PRIMARY KEY, name TEXT, topic TEXT);
    CREATE TABLE Users (id INTEGER PRIMARY KEY, name TEXT);
    CREATE TABLE UserInChat(
        chat_id INTEGER, 
        user_id INTEGER, 
        FOREIGN KEY (chat_id) REFERENCES Chats(id),
        FOREIGN KEY (user_id) REFERENCES Users(id),
        PRIMARY KEY (chat_id, user_id)
    );

    Что это нам даёт?
    - Наличие записи в UserInChat означает, что пользователь находится в чате.
    - Каждая запись в UserInChat ссылает на существующего пользователя и на существующий чат.
    - Сочетание пользователь-чат уникально, т.е. пользователь не может войти в один чат дважды (одновременно).
    - В то же время, могут быть записи с одним и тем же пользователем (один пользователь в нескольких чатах).
    - Могут быть записи с одним и тем же чатом (много пользователей в одном чате).

    Как узнать, какие пользователи находятся в чате? Используем запрос с JOIN.
    SELECT Users.id as userid, Users.name as username
    FROM Users INNER JOIN UserInChat ON Users.id = UserInChat.user_id
    WHERE UserInChat.chat_id = 123456;


    Для добавления пользователя в чат делаем INSERT INTO в таблицу UsersInChat. Для удаление - DELETE FROM. Тут всё как обычно.
    Ответ написан
  • Почему выдает ошибку Cannot choose from an empty sequence?

    Vindicar
    @Vindicar
    RTFM!
    visit = random.choice(urls)
    У тебя в urls пусто на момент вызова функции.

    urls = []  # в urls пусто
    
    # тут ты только определяешь функцию, но не вызываешь её
    def createlist(ids):
        global urls
        for id in ids:
            urls.append("https://scrap.tf/raffles/" + id)
    # так что тут urls всё ещё пуст
    # внутри login() вызывается rufflejoin(). А urls всё ещё пуст.
    login()
    Ответ написан
    Комментировать
  • Как отправлять текст соответствующий картинке в телеграм боте на Python?

    Vindicar
    @Vindicar
    RTFM!
    1. вынеси random.choice(os.listdir('test')) в переменную, например, img
    2. используй os.path.splitext(os.path.basename(img))[0], чтобы получить имя файла картинки без расширения
    3. Не забудь отправить файл через photo = open('test/' + img, 'rb')
    4. PROFIT
    Ответ написан
    2 комментария
  • Как сделать актуализацию данных?

    Vindicar
    @Vindicar
    RTFM!
    Используй on_conflict. Он позволяет как молча проигнорировать втавляемые данные, так и частично обновить существующую строку.
    Причем достаточно конфликта по ключу (id пользователя).

    Собственно, это хорошо работает, если тебе нужно просто хранить в базе всех, кто обращался к твоему боту.
    Если же тебе нужна именно своя регистрация (а тут надо дважды подумать - нужна ли? может, нафиг её?), то тогда сначала проверяй вручную, прошёл ли пользователь регистрацию.
    Ответ написан
    Комментировать
  • Как запускать Process в скриптах которые импорируются?

    Vindicar
    @Vindicar
    RTFM!
    AttributeError: Can't pickle local object 'start.<locals>.f1'

    Вынеси функцию, которую загоняешь в процесс, на верхний уровень модуля. Не делай её локальной в другой функции.
    Ответ написан
    Комментировать
  • Запускаю pyCharm и сразу открывается последний проект, как сделать что бы был выбор какой проект открыть?

    Vindicar
    @Vindicar
    RTFM!
    File -> Close Project. Закроет проект и покажет меню выбора проекта.

    Также есть настройка, Settings > Appearance & Behaviour > System Settings > Reopen projects on startup
    Ответ написан
    5 комментариев
  • Как в Python проверять, в каких скриптах какие ресурсы, импортируемые из других скриптов, используются?

    Vindicar
    @Vindicar
    RTFM!
    Ну вот тут ты столкнулся с проблемой изоляции изменений.
    Обозначим код, который предоставляет какую-то услугу, сервисом, а код, который эту услугу использует - клиентом.
    Тогда есть два типа изменений: изменение реализации сервиса и изменение интерфейса сервиса.

    Первое изменение затрагивает сервис, но необязательно затрагивает клиента. Если клиент обращается к сервису таким же образом, получает результат в таком же виде, получает сведения об ошибках таким же способом, то с точки зрения клиента изменения не было. Пусть даже в реальности сервис переписали с нуля.
    Пример: пусть у нас есть функция сортировки списка "на месте", т.е. изменяя этот список.
    def sort_list(original: list):
    Если раньше она сортировала список пузырьком, а потом мы её переписали на quicksort - с точки зрения кода, который эту функцию использует, ничего не изменится, кроме времени работы функции. Клиент все равно будет использовать функцию так:
    some_list = [ ... ]
    sort_list(some_list)


    Второй тип изменений меняет интерфейс сервиса, т.е. то, как он взаимодействует с клиентом.
    Продолжая пример, если мы решили, что теперь функция будет возвращать отсортированную копию списка, не трогая исходный список:
    def sort_list(original: list) -> list:
    Это изменение сломает клиентский код, так как ему теперь придётся использовать функцию так:
    some_list = [ ... ]
    some_list = sort_list(some_list)

    Т.е. наше изменение сломало обратную совместимость: старый код не может работать с новыми версиями.

    Если быть осторожным, то можно внести изменение в интерфейс, не сломав обратную совместимость. Например, если мы решили научить нашу функцию сортировать не только по возрастанию, но и по убыванию:
    def sort_list(original: list, inverse: bool = False):

    Тогда изначальный способ вызова sort_list(some_list) по прежнему будет работать. Мы расширили старый интерфейс, а не заменили его.

    Так вот, к чему я всё это говорю: умные IDE, вроде PyCharm, могут находить случаи использования того или иного элемента в рамках одного проекта (!). Но эта возможность очень ограничена, так как всегда можно так запутать код, что никакая IDE не разберётся.
    Поэтому лучше заранее продумывать, как клиентский код будет обращаться к услугам твоих сервисов, чтобы не пришлось переписывать интерфейс, а только реализацию.
    Ответ написан
    Комментировать
  • Бот рандомно выбирает вопрос, но проверяет по ответам для 1 вопроса, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    if x == 1:
        @bot.message_handler(content_types="text")
        def send(message):
            ...

    Так работать НЕ будет. Ты явно не очень понимаешь, что делаешь.

    1. Должна быть только одна функция, декорированная как @bot.message_handler(content_types="text"). Если их несколько, отработате только одна.

    2. Ты должен хранить сведения:
    - Какой вопрос был последним задан тому или иному пользователю
    - Какие вопросы были уже заданы тому или иному пользователю
    В рамках обучения их можно хранить в словаре, но в реальном боте потребуется постоянное хранилище (например, БД), в котором эти сведения пережили бы перезапуск бота

    3. Внутри обработчика @bot.message_handler ты должен получить ID пользователя, отправившего сообщение, взять из описанного выше хранилища номер последнего заданного вопроса (если есть), и уже на основании этого номера судить о том, правильный ли ответ.
    Ответ написан
  • Как склеить программно 2 изображения?

    Vindicar
    @Vindicar
    RTFM!
    Ну базовый вариант, если используешь OpenCV, ориентируйся на поиск локальных особенностей, а потом findHomography(), чтобы найти такое преобразование, которое переведёт точку на первом кадре в эквивалентную точку на втором. После этого warpPerspective(), чтобы преобразовать первый кадр в систему координат второго. Это должно совместить общие точки.

    Но это сработает только если на обоих кадрах есть достаточно контрастных общих точек, по которым их можно склеить.
    С другой стороны, если относительная позиция двух кадров не меняется со временем, то достаточно вычислить преобразование один раз на "удачной" паре кадров, и потом применять его ко всем парам.
    Ответ написан
    Комментировать
  • Как поделиться переменными между потоками из разных модулей?

    Vindicar
    @Vindicar
    RTFM!
    Для начала скажи, какую задачу ты пытаешься решить.
    Для случая с одноразовым потоком-воркером, тебе не нужна глобальная переменная. Достаточно класса.
    import threading
    
    class MyWorkerThread(threading.Thread):
        def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
            # поток не должен их менять!
            super().__init__()
            self.arg1 = arg1
            self.arg2 = arg2
            self.result: t.Optional[float] = None
        def run(self):
            time.sleep(10) # имитируем длительную работу
            self.result = self.arg1 + self.arg2

    И тогда ты можешь его использовать так:
    worker = MyWorkerThread(42, 69)
    worker.start()
    while True: 
        if worker.is_alive():  # проверяем, жив ли поток
            # делаешь ещё что-то, пока поток работает
            print('Still working...')
            time.sleep(0.5)
        else:
            # поток завершился, даём знать пользователю.
            print(f'Done! Result is {worker.result}!')
            break # выходим из цикла

    Если же тебе нужно просто дождаться конца потока, ничего не делая в процессе, можно сделать просто worker.join()

    Сложности начинаются, когда тебе нужно взаимодействовать с длительным потоком. Усложним пример:
    import threading, queue
    
    class MyWorkerThread(threading.Thread):
        def __init__(self, arg1: float, arg2: float): # передаём потоку входные данные 
            # поток не должен их менять!
            super().__init__()
            self.arg1 = arg1
            self.arg2 = arg2
            self.result: t.Optional[float] = None
            self.progress = queue.Queue()
        def run(self):
            for i in range(10):
                time.sleep(1) # имитируем длительную работу
                self.progress.put(i/10) # сообщаем о прогрессе
            self.result = self.arg1 + self.arg2
            self.progress.put(1.00)

    Тогда код использования изменится следующим образом:
    worker = MyWorkerThread(42, 69)
    worker.start()
    while True: 
        if worker.is_alive():  # проверяем, жив ли поток
            # делаешь ещё что-то, пока поток работает
            try:
                progress = worker.progress.get(block=True, timeout=0.5)
            except queue.Empty: # поток ничего не сообщил
                print('Still working...')
            else:
                print(f'Still working... {progress:.0%}')
                worker.progress.task_done() # один вызов task_done() на один успешный вызов get()!
        else:
            # поток завершился, даём знать пользователю.
            print(f'Done! Result is {worker.result}!')
            break # выходим из цикла

    Если тебе нужно передать потоку новые задания, то можешь использовать ещё одну queue.
    Ответ написан
    Комментировать
  • Как выполнять функцию каждую минуту в определенный интервал времени aioschedule?

    Vindicar
    @Vindicar
    RTFM!
    Вариант А. Выполнять каждые 5 минут, внутри функции проверять текущее время. Ничего не делать, если время не в заданном интервале.

    Варинат Б. Запланировать две функции. Одна, в 10:00, запустит через asyncio.create_task() простую зацикленную функцию, которая будет вызывать твою функцию, а потом делать await asyncio.sleep(300). Ссылку на задачу, возвращённую create_task(), надо будет сохранить в глобальную переменную.
    Другая функция, в 14:00, остановит эту задачу.

    Вариант А проще, и надёжнее в плане ситуации, когда программа запущена в промежуток между 10:00 и 14:00.
    Ответ написан
  • Multiprocessing.Process OSError: [WinError 87] Параметр задан неверно, что делать?

    Vindicar
    @Vindicar
    RTFM!
    Ну так тебе же говорят:
    _pickle.PicklingError: Can't pickle <function <lambda> at 0x00000122F23CEB00>: attribute lookup <lambda> on __main__ failed

    Для передачи данных в соседний процесс они сериализуются через модуль pickle. А сериализовываться так может далеко не всё.
    Если тебе нужно скинуть в соседний процесс код... это проблема. Может, получится скинуть словарь с локальными переменными, строку с кодом, и вычислить эту строку через eval() уже "на месте".
    Альтернативно, просто замени лямбду на нормальную функцию, и попробуй передать либо её, либо имя этой функции, чтобы дочерний процесс сам её взял из globals() или еще откуда.
    Ответ написан
    Комментировать
  • Как решить данную задачу на python?

    Vindicar
    @Vindicar
    RTFM!
    Вычисляешь корень, вычисляешь первый элемент последовательности - x, вычисляешь второй элемент (x + x/x) / 2.
    Потом в цикле, пока модуль (abs) разницы корня и последнего вычисленного элемента больше заданной точности, повторяешь вычисление. Предыдущему элементу previous присваиваешь последний элемент last, а последний элемент last вычисляешь как last = (x + x/previous) / 2. Считаешь итерации.
    Когда выйдешь из цикла, выводишь номер итерации, последний вычисленный элемент last, его отличие от реального корня.
    Ответ написан
  • Не работает replace в голосовом ассистенте?

    Vindicar
    @Vindicar
    RTFM!
    Ну ты же явно какую-то глупость делаешь.
    if cmd == "sreachyoutube":
            search_term = cmd.replace("Кеша видео", " ")

    Если в переменной cmd лежит строка sreachyoutube(!), то там по определению не может содержаться подстроки "Кеша видео".
    Ответ написан
    8 комментариев