U
U
UMFUCHI2021-10-16 19:44:54
Python
UMFUCHI, 2021-10-16 19:44:54

Can you help me understand the code?

There is a part of the code that was suggested to me here, but I don’t really understand how I should use it, the task of the code was to make the bot respond to 2 commands with 1 response. Here is the part of the code that was suggested:

if isinstance(condition, list):
            conditions = [el.lower() for el in condition]
            predicate = lambda text: any(condition in text for condition in conditions)
        elif isinstance(condition, str):
            condition = condition.lower()
            predicate = lambda text: condition in text
        elif callable(condition):
            predicate = condition
        else:
            raise TypeError('Condition must be either string or function!')

And here is the whole code:
import speech_recognition as sr
from gtts import gTTS
import random
import time
import datetime
import playsound

#Распознаватель речи
def listen_command(): 

    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("Скажите вашу команду: ")
        audio = r.listen(source)

    try:
        our_speech = r.recognize_google(audio, language="ru")
        print("Вы сказали: " + our_speech)
        return our_speech
    except sr.UnknownValueError:
        return "ошибка"
    except sr.RequestError:
        return "ошибка"


class VoiceCommandList:
    def __init__(self):
        self.actions = list()

    def on(self, condition):
        if isinstance(condition, str):
            condition = condition.lower()
            predicate = lambda text: condition in text
        elif callable(condition):
            predicate = condition
        else:
            raise TypeError('Condition must be either string or function!')

        def decorator(command_func):
            self.actions.append((predicate, command_func))
            return command_func

        return decorator

    def run_command(self, text):
        text = text.lower()
        for predicate, command in self.actions:
            if predicate(text):
                try:
                    response = command(text)
                    if response is None:
                        response = "Команда выполнена"
                except Exception as err:
                    response = "Ошибка при выполнении команды"
                    print(err)
                if response:
                    m.say_message(response)
                break
        else:
            m.say_message("Неизвестная команда")


vcl = VoiceCommandList()

#сама команда
@vcl.on('привет')
def hello(text):
    return "Здравствуйте, сэр!"

#То что говорит бот
def say_message(message):
    voice = gTTS(message, lang="ru")
    file_voice_name = "_audio_" + str(time.time()) + "_" + str(random.randint(0, 100000)) + ".mp3"
    voice.save(file_voice_name)
    playsound.playsound(file_voice_name)
    print("Голосовой ассистент: " + message)


if __name__ == '__main__':
    while True:
        command = listen_command()
        vcl.run_command(command)


I understand that it should work something like this:

@vcl.on('привет',  "здравствуй")
def hello(text):
    return "Здравствуйте, сэр!"


How can I use this part?
Please explain like a teapot, it is desirable to show how the modified parts of the code should look

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vindicar, 2021-10-17
@Vindicar

> I understand that it should work something like this:
> @vcl.on('hello', "hello")
> def hello(text):
You misunderstand. It might work if you passed
@vcl.on(['hello', "hello"]) #pay attention to the list!
Then, along with your suggestion to change on(), it would work. This is one way.
However, you didn't pay attention to this one:
@vcl.on('hello')
@vcl.on("hello")
def hello(text):
That should work too! The list makes sense if you load this list from somewhere, and do not write it as a constant in the script code.
In general, I would advise using regular expressions. More or less like this:

import re
#.............................................
    def on(self, condition):
        if isinstance(condition, re.Pattern):
            predicate = lambda text: condition.match(text)
        elif isinstance(condition, str):
            condition = condition.lower()
            predicate = lambda text: condition in text
        elif callable(condition):
            predicate = condition
        else:
            raise TypeError('Condition must be either string or function!')

        def decorator(command_func):
            self.actions.append((predicate, command_func))
            return command_func

        return decorator

To make it more convenient, you can fix the run_command() method so that the result of the match is available to the command handler.
def run_command(self, text):
        text = text.lower()
        for predicate, command in self.actions:
            res = predicate(text) #сохраняем результат
            if res:
                try:
                    response = command(text, res) #теперь обработчик принимает два аргумента!
                    if response is None:
                        response = "Команда выполнена"
                    else:
                        response = str(response)
                except Exception as err:
                    response = "Ошибка при выполнении команды"
                    print(err)
                if response:
                    m.say_message(response)
                break
        else:
            m.say_message("Неизвестная команда")

And an example usage would be something like this:
#нужно знать синтаксис регулярных выражений
#совпадёт с любой строкой, начинающейся строго со слов "скажи" или "произнеси"
#всё что после этих слов попадёт в отдельную группу 1.
@vcl.on(re.compile('^(?:скажи|произнеси) (.+)$', re.I)) 
def hello(text, match): #все обработчики будут принимать два аргумента!
    #match будет содержать результат сопоставления входной строки с регуляркой
    #group(1) будет содержать то, что оказалось на месте (.+)
    return match.group(1) #пусть бот повторит то, что мы попросили его сказать

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question