高复杂度防止功能

问题描述

首先,因为我使用的代码很大,所以 here代码链接

如果给出特定输入,我有这个函数会运行其他函数

allowed_commands = ['help','joblist','job','jobresign','work','bal','balance','dep','deposit','with','withdraw','fish','hunt','shop','buy','sell','multiply']

def gamePlay():
    while True:
        command = input(f"{bright_green}Command (type [help] to see list of all commands):\n>> ")
        while command in allowed_commands:
            # <-- display Rules -->
            if command == 'help':
                rules()
                break

            # <-- display Jobs -->
            elif command == 'joblist':
                joblist_function()
                break

            # <-- Get Jobs -->
            elif command == 'job' and working == False:
                job_funtion()
                break

            elif command == 'job' and working == True:
                print(f"\n{red}You are already doing a job. You can't work on two jobs,that is dumb...\n")
                break

            # <-- Resign Job -->
            elif command == 'jobresign':
                job_resign()
                break

            # <-- Work -->
            elif command == 'work' and working == True:
                work()
                break
            
            elif command == "work" and working == False:
                print(f"{red}\nLOL,you don't have a job,how you gonna work?\n")
                break

            # <-- Deposit -->
            elif command == 'dep' or command == 'deposit' and deposit_allowed != deposited:
                dep_money()
                break

            elif command == 'dep' or command == 'deposit' and deposit_allowed == deposited:
                print("You have a full bank kiddo...")
                break

            # <-- Balance -->
            elif command == 'bal' or command == 'balance':
                display_balance()
                break

            # <-- Withdraw -->
            elif command == 'with' or command == 'withdraw' and deposited != 0:
                withdraw_money()
                break
            
            elif command == 'with' or command == 'withdraw' and deposited == 0:
                print(f"{red}\nNo money deposited. What are you even trying to wothdraw LOL?\n")
                break

            elif command == 'shop':
                shop()
                break

            elif command == 'beg':
                beg()
                break
def beg():
    global money
    random_number2 = random.choice([0,1,2])
    random_money = random.choice(range(100,500))

    if random_number2 == 1:
        print("Ewwww beggar. No stonks for u")
    
    if random_number2 == 2:
        print(f"Mr.beggar,you can have ⏣ {random_money}.")
        money += random_money

但是函数下绿线上的工具提示说“圈复杂度太高:17(阈值15)”。

enter image description here

通常,即使复杂度高达 30,这也适用于我的代码。但最后一个 elif 之后的代码不起作用。即使我输入“beg”,该函数也不会运行:

Command (type [help] to see list of all commands):
>> beg
Command (type [help] to see list of all commands):
>> beg
Command (type [help] to see list of all commands):
>> 

为什么会发生这种情况,我该如何解决

解决方法

根据 sonarQube 文档,

根据通过代码的路径数计算圈复杂度。每当函数的控制流分裂时,复杂度计数器就会增加 1。每个函数的最小复杂度为 1。此计算因语言而异,因为关键字和功能确实如此。

虽然这种圈复杂度可能会因语言而异,但通常情况下,循环和条件共同构成了 30 的圈复杂度。总结以下关键词,我们可以估计圈复杂度为 30(注意,真正的算法可能不一样)。

    while 
        while  
            if ... 
            elif ... 
            elif ... and ... 
            elif ... and ...  
            elif ... 
            elif ... and ... 
            elif ... and ... 
            elif ... or  ... and ... 
            elif ... or  ... and ... 
            elif ... or  ... 
            elif ... or  ... and ... 
            elif ... or  ... and ... 
            elif ... 
            elif ... 

虽然更高的圈复杂度在代码中不是一个好的做法,但这只是一个警告,您的代码将像往常一样编译。

就您而言,不执行您的 beg 命令的问题是,您的 beg 中不存在 allowed_commands

,

您可以像这样使用字典:

{
    'help': rules,'joblist': joblist_function,}[command]()

但是你也可以像这样进行一些重构:

from typing import Callable,Dict


class Game:
    def __init__(self) -> None:
        self.deposit_allowed = 1000
        self.deposited = 0

    def play(self) -> None:
        commands = self._get_commands()

        while True:
            command = input(f"{bright_green}Command (type [help] to see list of all commands):\n>> ")

            if command not in commands:
                print('Wrong command!')
                continue

            commands[command]()

    def _get_commands(self) -> Dict[str,Callable[[],None]]:
        return {
            'help': self._rules,'joblist': self._joblist_function,'deposit': self._deposit_money,'dep': self._dep_money,# ...
        }

    def _rules(self) -> None:
        pass

    def _joblist_function(self) -> None:
        pass

    def _deposit_money(self) -> None:
        if self.deposit_allowed == self.deposited:
            print("You have a full bank kiddo...")
            return

        self._dep_money()

    def _dep_money(self) -> None:
        pass


Game().play()