Как уменьшить цикломатическую сложность моего кода?

Итак, я пытаюсь создать чат-бот на питоне. Онлайн-идео (repl.it) — это то, что я использую для запуска кода из любого места. Он имеет цикломатический предел сложности 15. Я хотел бы сделать что-то действительно сложное, не выходя за этот предел. Возможно ли это?

import random

greeting = ["Hello!","Hi!","Hey!","Hello my name is IFuture!","How may I help you?"]
farewell = ["Bye","Bye bye","See you soon","Don't forget about me!","See you next time","See you"]
catchthat = ["I didn't catch that.","Sorry, I couldn't understand what you said.","Could you say that again?","Could you type in english?"]
notnice = ["That wasn't nice.","Next time try to say that nicer.","Try being nice.","You have more friends when you are nice."]
def run():
  global greeting,farewell,catchthat
  userinputa = str(input(">>>")).lower()
  userinput = userinputa.split()
  if "hello" in userinput or "hey" in userinput or "hi" in userinput: 
    print(random.choice(greeting))
  elif  "swear1" in userinput or "swear2" in userinput or "swear3" in userinput or "swear4" in userinput or "swear6" in userinput:
    if "you" in userinput:
      print(random.choice(swear back)
    else:
      #print(random.choice(notnice))
      print("swear back")
  elif "what" in userinput:
    if "can" in userinput:
      if "you" in userinput:
        if "do" in userinput:
          print("Try ?help or anything I am made to do.")
    elif "is" in userinput:
      try:
        num1 = int(userinput[2])
        num2 = int(userinput[4])
        conversion = str(userinput[3])
        if conversion in ["add","plus","addition","sum","+"]:
          print(num1+num2)
        elif conversion in ["times","multiply","*","x"]:
          print(num1*num2)
        elif conversion in ["divide","/"]:
          print(num1/num2)
      except:
        print("Try using spaces for example 5*5 would be 5 * 5.")
  else:
    print(random.choice(catchthat))




while True:
  run()

Извините за мой ужасно неэффективный код.


person FluxedScript    schedule 15.08.2019    source источник
comment
на этом сайте lizard.ws у вас есть цикломатическая сложность 19   -  person kederrac    schedule 15.08.2019
comment
Позволяет ли он запускать и размещать ваш код бесплатно?   -  person FluxedScript    schedule 15.08.2019
comment
Попробуйте разбить метод run на более мелкие методы.   -  person Stephen C    schedule 15.08.2019
comment
что вы хотели этой строкой: print(random.choice(клянусь в ответ). Код не работает   -  person kederrac    schedule 15.08.2019
comment
В принципе, у меня не могло быть строки, которая ругалась бы на пользователя - так как я не хочу модерироваться   -  person FluxedScript    schedule 15.08.2019
comment
print(random.choice(присягнуть) или print('присягнуть') на данный момент (иначе ваш код не запустится)   -  person kederrac    schedule 15.08.2019
comment
Хорошо, исправил код и исправил небольшую логическую ошибку   -  person FluxedScript    schedule 15.08.2019
comment
random.choice(присягнуть) => переменные swear и back не определены, просто используйте присягу   -  person kederrac    schedule 15.08.2019
comment
Цикломатическая сложность не мешает вашему коду работать, так что это, вероятно, больше подходит для codereview.stackexchange.com.   -  person chepner    schedule 15.08.2019


Ответы (1)


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

Я только что уменьшил цикломатическую сложность кода функции "запустить" с 19 до 3 (согласно этому сайту):

from itertools import chain    
import random

GREETING = ["Hello!","Hi!","Hey!","Hello my name is IFuture!","How may I help you?"]
FAREWELL = ["Bye","Bye bye","See you soon","Don't forget about me!","See you next time","See you"]
CATCHTHAT = ["I didn't catch that.","Sorry, I couldn't understand what you said.","Could you say that again?","Could you type in english?"]
NOTNICE = ["That wasn't nice.","Next time try to say that nicer.","Try being nice.","You have more friends when you are nice."]

USER_GREETING = frozenset({"hello", "hey", "hi"})
USER_SWEAR = frozenset({"swear1",  "swear2", "swear3",  "swear4", "swear6"})

def print_sum(x, y): 
    print(x + y)

def print_mul(x, y):
    print(x * y)

def print_div(x, y):
    print(x / y)

CONVERSATION_OPERATION = {"add" : print_sum,
    "plus" : print_sum,
    "addition" : print_sum,
    "sum" : print_sum,
    "+" : print_sum,
    "times" : print_mul,
    "multiply" : print_mul,
    "*" : print_mul,
    "x" : print_mul,
    "divide" : print_div,
    "/" : print_div
}

def swer_response(userinput):
    if "you" in userinput:
        return 'swear back1'

    #print(random.choice(notnice))
    return "swear back2"

def what_is(userinput):
    try:
        num1 = int(userinput[2])
        num2 = int(userinput[4])
        conversion = str(userinput[3])
        print_operation = CONVERSATION_OPERATION[conversion]
        print_operation(num1, num2)
    except:
        print("Try using spaces for example 5*5 would be 5 * 5.")

WHAT_CAN_YOU_DO = frozenset({"what", "can", "you","do" })
WHAT_IS = frozenset({"what", "is"})

REPLY_SEQ_AT_LEAST_ONE = [USER_GREETING, USER_SWEAR]
REPLY_SEQ_SUBSET = [WHAT_CAN_YOU_DO, WHAT_IS]

REPLY = {
    USER_GREETING: lambda _:  print(random.choice(GREETING)),
    USER_SWEAR: lambda x:  print(swer_response(x)),
    WHAT_CAN_YOU_DO: lambda _: print("Try? help or anything I am made to do."),
    WHAT_IS: lambda x: what_is(x)
}

def at_least_one_word(userinput):
    yield from (r for r in REPLY_SEQ_AT_LEAST_ONE if r.intersection(userinput))

def subset(userinput):
    yield from (r for r in REPLY_SEQ_SUBSET if r.issubset(userinput))


def run():
    userinputa = str(input(">>>")).lower()
    userinput = set(userinputa.split()) 

    for reply in chain(at_least_one_word(userinput), subset(userinput)) :
        if reply.intersection(userinput):
            reply_func = REPLY[reply]
            reply_func(userinput)
            return

    print(random.choice(CATCHTHAT))


run()
person kederrac    schedule 15.08.2019