Python Forum

Full Version: Class positional argument error
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi all! I'm new to Python and programming and I am asking for your help, again (I truly appreciate you taking the time and effort to help). I am working on a homework assignment that involves using the turtle module to draw a chessboard (incorporating class). I have, previously, done this assignment via functions and pulled that code to use to define methods within the class (and so I know that the code to draw the chessboard, itself, worked). All must be private except for the draw method which will be called from my main file.
Here is the issue I am running in to. My main file looks as follows:
import turtle
from chessboard import Chessboard

def main():
    startX, startY = eval(input("Enter a starting point: "))
    width = input("Input a width: ")
    height = input("Input a height: ")

    if width == "" and height == "":
        chessboard = Chessboard(startX, startY)
    elif height == "":
        chessboard = Chessboard(startX, startY, width=eval(width))
    elif width == "":
        chessboard = Chessboard(startX, startY, height=eval(height))
    else:
        chessboard = Chessboard(startX, startY, eval(width), eval(height))

    chessboard.draw(startX, startY, width, height)

    turtle.hideturtle()
    turtle.done()


main()
(I am aware that eval makes the code vulnerable - but this is how we are supposed to do it). And here is my class:
import turtle

class Chessboard:
        def __init__(self, startX, startY, width=250, height=250):
            self.__startX = startX
            self.__startY = startY
            self.__width = width
            self.__height = height

        def draw(self, __startX, __startY, __width=250, __height=250):
            turtle.clear
            self.__drawChessboard(self, __startX, __startY, __width, __height)

        def __drawChessboard(self, __startX, __startY, __width=250, __height=250):
            # uses height x width, default 250
            turtle.setheading(0) # position cursor
            turtle.penup()  # raise pen
            turtle.goto(__startX, __startY) # goto starting location
            turtle.pendown() # pen down
            # draws the board outline
            turtle.goto(__startX + __width, __startY)
            turtle.goto(__startX + __width, __startY + __height)
            turtle.goto(__startX, __startY + __height)
            turtle.goto(__startX, __startY)

            #call __drawAllRectangles() to draw checkers
            self.__drawAllRectangles(self, __startX, __startY, __width, __height)

            #turtle window closes with user click
            turtle.exitonclick()


        def __drawAllRectangles(self, __startX, __startY, __width, __height):
            #determine width and height of individual checkers
            __checkerWidth = __width / 8
            __checkerHeight = __height / 8
            #draws all checkers
            for row in range(8):
                for column in range(4):
                    if row % 2 == 0:
                        #call drawRectangle() to draw individual checkers
                        self.__drawRectangle(self, __startX + (2 * column * __checkerWidth),
                                             __startY + (row * __checkerHeight), __checkerWidth, __checkerHeight)
                    else:
                        self.__drawRectangle(self, __startX + __checkerWidth + (2 * column * __checkerWidth),
                                             __startY + (row * __checkerHeight), __checkerWidth, __checkerHeight)


        def __drawRectangle(self, __startX, __startY, __checkerWidth, __checkerHeight):
            # draws single black checker
            turtle.penup()
            turtle.setheading(0)
            turtle.goto(__startX, __startY)
            turtle.fillcolor("black")
            turtle.begin_fill()
            turtle.pendown()
            turtle.goto(__startX + __checkerWidth, __startY)
            turtle.goto(__startX + __checkerWidth, __startY + __checkerHeight)
            turtle.goto(__startX, __startY + __checkerHeight)
            turtle.goto(__startX, __startY)
            turtle.end_fill()
When I run my main file, it prompts me to enter a start point, width, and height. When I have done these, I get the error:

Error:
Traceback (most recent call last): File "", line 30, in <module> main() File "", line 24, in main chessboard.draw(startX, startY, width, height) File "", line 18, in draw self.__drawChessboard(self, __startX, __startY, __width, __height) TypeError: __drawChessboard() takes from 3 to 5 positional arguments but 6 were given
I don't understand this error. Huh Can you help me figure this out?
Can you show also your input (i.e. everything IO).
One thing I notice is that height and width will be str as you don't eval on them. It's good you know that eval can be harmful in such use
The problem is chessboard.py line 12:

self.__drawChessboard(self, __startX, __startY, __width, __height)
That method, defined on line 14 has the signature:

def __drawChessboard(self, __startX, __startY, __width=250, __height=250):
The first parameter of a method signature is self-referential and automatically passed in when the method is called. Because your call on line 12 passes "self" as an argument, you are effectively doing this:

self.__drawChessboard(self, self, __startX, __startY, __width, __height)
The traceback states that the method takes 3 to 5 arguments because it requires __startX and __startY and automatically includes self (3 arguments) and the two keyword arguments for __width and __height (for 5 arguments). The call above includes self twice which brings your number of arguments to six.

On a side note, since your __init__() sets four attributes, you do not have to provide those as arguments for your methods. You can refactor __drawChessboard() as follows with no issues:

def __drawChessboard(self, __width=250, __height=250):
    # uses height x width, default 250
    turtle.setheading(0) # position cursor
    turtle.penup()  # raise pen
    turtle.goto(self.__startX, self.__startY) # goto starting location
    turtle.pendown() # pen down
    # draws the board outline
    turtle.goto(self.__startX + __width, self.__startY)
    turtle.goto(self.__startX + __width, self.__startY + __height)
    turtle.goto(self.__startX, self.__startY + __height)
    turtle.goto(self.__startX, self.__startY)

    #call __drawAllRectangles() to draw checkers
    self.__drawAllRectangles(self, self.__startX, self.__startY, __width, __height)

    #turtle window closes with user click
    turtle.exitonclick()