2

I have a class named Board that acts as a superclass. It is basically a randomly generated Sudoku Board with 81 numbers placing correctly on it by the rules.

Then I defined a subclass named normalSudoku where it will be initialized with a parameter "difficulties"(a string) where it will decide how many empty entries will appear on the Sudoku.

When I created an instance of normalSudoku and try to print it out to see if it works, the following error pops out:

TypeError: module.__init__() takes at most 2 arguments (3 given)

I am not sure what I did wrong and I am a bit confused about the use of self and object initialization in python.

My Board Class:

class Board(object):    
    def __init__(self):
        self.sudoku = self.__create__()

    def __create__(self):
       #generateion of board goes here
       #it will return a 9x9 2d-list

My normalSudoku Class:

import Board
import random

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

    def Create_Empty_Entries(self, difficulties):
        numbers = list(range(0,9))
        if difficulties == "Easy":
            for x in range(25):
                a = random.choice(numbers)
                b = random.choice(numbers)
                self.sudoku[a][b] = None
        elif difficulties == "Medium":
            for x in range(35):
                a = random.choice(numbers)
                b = random.choice(numbers)
                self.sudoku[a][b] = None
        elif difficulties == "Hard":
            for x in range(45):
                a = random.choice(numbers)
                b = random.choice(numbers)
                self.sudoku[a][b] = None
        elif difficulties == "Expert":
            for x in range(65):
                a = random.choice(numbers)
                b = random.choice(numbers)
                self.sudoku[a][b] = None
        else:
            print("The Level of Difficulty you chose does not exist.")
Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
  • Does this answer your question? [TypeError: module.\_\_init\_\_() takes at most 2 arguments (3 given)](https://stackoverflow.com/questions/14583761/typeerror-module-init-takes-at-most-2-arguments-3-given) – Josh Correia Sep 14 '20 at 19:10

2 Answers2

5

You are trying to create a subclass of a module, not your base class.

You import the module here:

import Board

then try to subclass that directly:

class normalSudoku(Board):

Board is the module. If the class is named the same, it's an attribute on the module:

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

You already had the __init__ call call correct, just not the base class reference.

Alternatively, import the class from the module:

from Board import Board

and leave your class definition the same but adjust the __init__ call:

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

Some other pointers:

  • Don't use __name__ dunder (double underscore) names. Those are reserved by Python for future system use, and thus can lead to forward compatibility issues.

  • Try to follow the Python PEP 8 naming conventions; it'll lead to more clarity. Modules are generally named using lower_case_with_underscores names, classes use CamelCase. Your module should be named board, the class Board, making the difference obvious. The same goes for methods; those should be lowercase too.

Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
  • Thank you very much for pointing out my mistakes! Your answer is really helpful. I have fixed all the errors now and had a better understanding of classes structure in python. :) –  Sep 09 '17 at 13:43
1

In addtition to Martjin Pieters' answer, your line self.Create_Empty_Entries(self,difficulties) is also incorrect, it should be self.Create_Empty_Entries(difficulties).

Consider this :

>>> class Foo(object):
    def foo(self):
        return self


>>> print Foo
<class '__main__.Foo'>
>>> instance = Foo()
>>> print instance
<__main__.Foo object at 0x02FFF7F0>
>>> print instance.foo() #as you can see, I don't pass any argument here
<__main__.Foo object at 0x02FFF7F0> #however you can note that internally, "instance" passed itself as "foo()" first argument
  • yeah that too, I could say that when a class calls its member function, it automatically passes itself as its first argument right? –  Sep 09 '17 at 14:12
  • Yup, but not quite : you've got it, but just be sure to make the difference between the class, and its instance. There are subtleties. Your satement is correct if the method called is a "classmethod" (defined with the decorator `@classmethod`. For what you mean, you should say : When an instance calls its member method, it automatically passes itself as its first argument – Nicolas David Sep 09 '17 at 14:47