在python中简化一个函数中重复的多if-elif语句和多个循环有困难

在python中简化一个函数中重复的多if-elif语句和多个循环有困难,python,performance,coding-style,code-cleanup,coding-efficiency,Python,Performance,Coding Style,Code Cleanup,Coding Efficiency,我对Python非常陌生 我坚信简单、简洁、高效的算法设计和编码风格。在学习Python的过程中,我意识到Python在幕后做了很多事情,因此语言本身对程序员非常友好。这很好,但我想深入了解我在编码时可以做什么优化或保持什么习惯。今天我遇到了麻烦,简化了我的代码 以下函数用于根据所选的难度级别在数独板上创建空白点 这是我的密码: class normalSudoku(Board): def __init__(self,difficulties): super.__init

我对Python非常陌生

我坚信简单、简洁、高效的算法设计和编码风格。在学习Python的过程中,我意识到Python在幕后做了很多事情,因此语言本身对程序员非常友好。这很好,但我想深入了解我在编码时可以做什么优化或保持什么习惯。今天我遇到了麻烦,简化了我的代码

以下函数用于根据所选的难度级别在数独板上创建空白点

这是我的密码:

class normalSudoku(Board):
    def __init__(self,difficulties):
        super.__init__()
        self.Create_Empty_Entries(difficulties)


    def Create_Empty_Entries(self,difficulties):
        numbers = list(range(0,9))
        if difficulties == "Easy":
            for x in range(25):
                a,b = choice(numbers),choice(numbers)
                if self.sudoku[a][b] != None:
                    self.sudoku[a][b] = None
                    self.holes += 1
                self.holes += 1
            return None

        elif difficulties == "Medium":
            for x in range(35):
                a,b = choice(numbers),choice(numbers)
                if self.sudoku[a][b] != None:
                    self.sudoku[a][b] = None
                    self.holes += 1
            return None

        elif difficulties == "Hard":
            for x in range(45):
                a,b = choice(numbers),choice(numbers)
                if self.sudoku[a][b] != None:
                    self.sudoku[a][b] = None
                    self.holes += 1
            return None

        else:
            for x in range(65):
                a,b = choice(numbers),choice(numbers)
                if self.sudoku[a][b] != None:
                    self.sudoku[a][b] = None
                    self.holes += 1
            return None
正如你所看到的,这是非常重复的。任何关于简化它或更有效的编码风格的想法都将受到欢迎

另外,在性能和内存使用方面,有没有更好的方法在python中初始化类而不是调用
\uuu init\uuu()
?就像C++一样,还有一个更干净和更快的初始化列表。
请随意指出我犯的错误。如有任何建议,将不胜感激。谢谢

因为唯一改变的是从中选择的数字范围,我建议创建一个dict,其中难度映射到该数字,然后在设置数字的单个函数中使用它

class normalSudoku(Board):
    def __init__(self,difficulties):
        super.__init__()
        self.Create_Empty_Entries(difficulties)


    def Create_Empty_Entries(self,difficulties):
        numbers = list(range(0,9))
        difficulty_values = {'Easy':25,'Medium':35, 'Hard':45, 'Default':65}

        # check the difficulty level exists in the dict. 
        # If it does, use that value, if it doesn't then use the default value
           difficulty = difficulty_values.get(difficulties, difficulty_values['Default'])

            # now use that difficulty to set the numbers once.
            for x in range(difficulty):
            a,b = choice(numbers),choice(numbers)
            if self.sudoku[a][b] != None:
                self.sudoku[a][b] = None
                self.holes += 1
            self.holes += 1
    return None

因为唯一改变的是从中选择的数字范围,我建议创建一个dict,其中难度映射到该数字,然后在设置数字的单个函数中使用它

class normalSudoku(Board):
    def __init__(self,difficulties):
        super.__init__()
        self.Create_Empty_Entries(difficulties)


    def Create_Empty_Entries(self,difficulties):
        numbers = list(range(0,9))
        difficulty_values = {'Easy':25,'Medium':35, 'Hard':45, 'Default':65}

        # check the difficulty level exists in the dict. 
        # If it does, use that value, if it doesn't then use the default value
           difficulty = difficulty_values.get(difficulties, difficulty_values['Default'])

            # now use that difficulty to set the numbers once.
            for x in range(difficulty):
            a,b = choice(numbers),choice(numbers)
            if self.sudoku[a][b] != None:
                self.sudoku[a][b] = None
                self.holes += 1
            self.holes += 1
    return None

您可以向类中添加检查方法:

# add this to the class body
def auto_increment(self, a, b):
    if self.sudoku[a][b] != None:
       self.sudoku[a][b] = None
       self.holes += 1
    self.holes += 1
    return
然后,您可以使用以下方法将参数传递给您的方法:

self.auto_increment(choices(number), choices(number))
插槽是减少内存使用的有效方法

您可以在类中添加检查方法:

# add this to the class body
def auto_increment(self, a, b):
    if self.sudoku[a][b] != None:
       self.sudoku[a][b] = None
       self.holes += 1
    self.holes += 1
    return
然后,您可以使用以下方法将参数传递给您的方法:

self.auto_increment(choices(number), choices(number))
插槽是减少内存使用的有效方法

一个选项是将参数从代码移到数据,然后对数据进行操作:

# You could source these two dicts from elsewhere, like a JSON/YAML/config file
difficulties = {
  Easy: {
    size: 25
  },
  Medium: {
    size: 35
  },
  Hard: {
    size: 45
  }
}

defaultDifficulty = {
  size: 65
}

# ...

def Create_Empty_Entries(self, difficultyName):
  if difficultyName in difficulties:
    difficulty = difficulties[difficultyName]
  else:
    difficulty = defaultDifficulty

  numbers = list(range(0,9))
  for x in range(difficulty.size):
    a,b = choice(numbers),choice(numbers)
    if self.sudoku[a][b] != None:
      self.sudoku[a][b] = None
      self.holes += 1

一个选项是将参数从代码移动到数据,然后对数据进行操作:

# You could source these two dicts from elsewhere, like a JSON/YAML/config file
difficulties = {
  Easy: {
    size: 25
  },
  Medium: {
    size: 35
  },
  Hard: {
    size: 45
  }
}

defaultDifficulty = {
  size: 65
}

# ...

def Create_Empty_Entries(self, difficultyName):
  if difficultyName in difficulties:
    difficulty = difficulties[difficultyName]
  else:
    difficulty = defaultDifficulty

  numbers = list(range(0,9))
  for x in range(difficulty.size):
    a,b = choice(numbers),choice(numbers)
    if self.sudoku[a][b] != None:
      self.sudoku[a][b] = None
      self.holes += 1

我刚刚读了关于
\uuuuuuuuuuuuuuuuuu
的文档。我学到了很多,谢谢!我刚刚读了关于
\uuuuuuuuuuuuuuuuuu
的文档。我学到了很多,谢谢!使用
dict.get
会有不同的性能吗?或者只是更干净?不确定是否更快,尽管在这种情况下,代码更少。虽然我理解它更安全——因为它保证为dict键返回一个值,即使它不存在(默认情况下不会得到任何值)。这样你就不会碰到异常,我明白了。谢谢你的润肤露使用dict.get是否会有不同的性能?或者它只是更干净?不确定是否更快,尽管在这种情况下代码更少。虽然我理解它更安全——因为它保证为dict键返回一个值,即使它不存在(默认情况下不会得到任何值)。这样你就不会碰到异常,我明白了。感谢来自其他地方的lotBy源代码。您的意思是我可以创建另一个模块并将字典放在那里,还是创建一个.txt文件并将它们写入其中?在采购时,我应该使用哪个关键字,导入还是使用?采购的优势是什么?两者都是有效的选择;这取决于您希望如何生成/维护这些数据,以及您是否希望能够在不重新启动程序的情况下重新加载困难。如果您不打算让它比上面复杂得多,那么您最好将对象保留在同一个模块中,这实际上是@MattWBP的答案。将数据与代码分离的优点是两者都可以彼此独立地发展。您可以调整范围大小(或其他未来参数),而无需更改代码。如果需要,它还可以实时重新加载困难。通过从其他地方获取它,您的意思是我可以创建另一个模块并将字典放在那里/或创建一个.txt文件并将它们写入其中?在采购时,我应该使用哪个关键字,导入还是使用?采购的优势是什么?两者都是有效的选择;这取决于您希望如何生成/维护这些数据,以及您是否希望能够在不重新启动程序的情况下重新加载困难。如果您不打算让它比上面复杂得多,那么您最好将对象保留在同一个模块中,这实际上是@MattWBP的答案。将数据与代码分离的优点是两者都可以彼此独立地发展。您可以调整范围大小(或其他未来参数),而无需更改代码。如果需要的话,它还可以让现场重新加载困难。