Python Forum
another positional argument error (...and executing objects stored in a list)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
another positional argument error (...and executing objects stored in a list)
#1
Okay, Python gurus - your help solving this issue, please?

I am writing a program that asks a user to make a selection to enter information that is used to create an instance of a class that is then stored in a list to be called upon for drawing (using turtle). I have two different classes: Circle and Rectangle. Here is my main code:

from circle import Circle
from rectangle import Rectangle

def main():
    playAgain = True

    list = []

    while playAgain:
        print("1) Enter Circle")
        print("2) Enter Rectangle")
        print("3) Remove Shape")
        print("4) Draw Shapes")
        print("5) Exit")
        menu = int(input("What would you like to do? "))

        color_list = ["red", "yellow", "blue", "green"]

        # Enter Circle
        if menu == 1:
            centerX, centerY = eval(input("Enter the center position (x,y): "))
            radius = eval(input("Enter radius: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False
            circle = Circle(centerX, centerY, radius, color)
            list.append(circle)

        # Enter Rectangle
        if menu == 2:
            startX, startY = eval(input("Enter the starting position (x,y): "))
            height = eval(input("Enter height: "))
            width = eval(input("Enter width: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False

            rectangle = Rectangle(startX, startY, height, width, color)
            list.append(rectangle)

        # Remove Shape
        if menu == 3:
            if len(list) > 0:
                print("The list contains", len(list), "objects.")
                remove = int(input("Please select an item from 1 to " + str(len(list)) + " to remove that object:"))

                del list[remove - 1]

            else:
                print("The list contains no objects.")

        # Draw Shapes
        if menu == 4:
            for circle in list:
                circle.draw(centerX, centerY, radius, color)
            for rectangle in list:
                rectangle.draw(startX, startY, height, width, color)

        # Exit
        if menu == 5:
            playAgain = False

    print()
    print("Thank you for playing.")


main()
Here is my circle code:

import turtle

class Circle:
    def __init__(self, centerX, centerY, radius, color):
        self.centerX = centerX
        self.centerY = centerY
        self.radius = radius
        self.color = color

    def draw(self, centerX, centerY, radius, color):
        turtle.hideturtle()
        turtle.penup()
        turtle.setheading(0)
        turtle.pencolor(color)
        turtle.goto(centerX, centerY - radius)
        turtle.pendown()
        turtle.fillcolor(color)
        turtle.begin_fill()
        turtle.circle(radius)
        turtle.penup()
        turtle.end_fill()
Here is my rectangle code:
class Rectangle:
    def __init__(self, startX, startY, height, width, color):
        self.startX = startX
        self.startY = startY
        self.height = height
        self.width = width
        self.color = color

    def draw(self, startX, startY, width, height, color):
        turtle.hideturtle()
        turtle.setheading(0)
        turtle.penup()
        turtle.goto(startX, startY)
        turtle.pencolor(color)
        turtle.fillcolor(color)
        turtle.pendown()
        turtle.begin_fill()
        turtle.forward(width)
        turtle.right(90)
        turtle.forward(height)
        turtle.right(90)
        turtle.forward(width)
        turtle.right(90)
        turtle.forward(height)
        turtle.end_fill()
        turtle.penup()
When I select to enter a circle, I am able to input all of the info and it appears to store it as an object in the list (when I use
print(list)
to verify). The same is true of adding a Rectangle object to the list. The issue I am encountering is when I go to draw the objects. The turtle window will open and the first object will draw, but then I am getting the following error:

Error:
Traceback (most recent call last): File "", line 107, in <module> main() File "", line 87, in main circle.draw(centerX, centerY, radius, color) TypeError: draw() missing 1 required positional argument: 'color'
The turtle will draw the first shape and fill it in with the color selected for the last object, but then it immediately gives me this error.

(Also, I know eval is not best practice - but it is how we have been told to do assignments in this class.)

Thank you for your time and effort.
Reply
#2
when you iterate over element in the list like this
for circle in list:
it doesn't matter you say circle, it iterates over all elements in the list - both instances of class Circle and instances of class Rectangle, i.e. it does not filter just circles. So I guess you have both circles and rectangles in the list and when there is error your 'circle' is actually instance of class Rectangle and expect 5 arguments, not 4

Not related to your problem, but as an advise - don't use list as variable name, it's built-in function and it will not be available to you.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
Thanks for your help. I've changed the name of my list to shape_list and used if/elif statements to check the type of object in the list before executing draw() from class Circle or class Rectangle:

main code:
from circle import Circle
from rectangle import Rectangle
import turtle

def main():
    playAgain = True

    shape_list = []

    while playAgain:
        print("1) Enter Circle")
        print("2) Enter Rectangle")
        print("3) Remove Shape")
        print("4) Draw Shapes")
        print("5) Exit")
        menu = int(input("What would you like to do? "))

        color_list = ["red", "yellow", "blue", "green"]

        # Enter Circle
        if menu == 1:
            centerX, centerY = eval(input("Enter the center position (x,y): "))
            radius = eval(input("Enter radius: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False

            circle = Circle(centerX, centerY, radius, color, "circle")
            shape_list.append(circle)

        # Enter Rectangle
        if menu == 2:
            startX, startY = eval(input("Enter the starting position (x,y): "))
            height = eval(input("Enter height: "))
            width = eval(input("Enter width: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False

            rectangle = Rectangle(startX, startY, height, width, color, "rectangle")
            shape_list.append(rectangle)

        # Remove Shape
        if menu == 3:
            if len(shape_list) > 0:
                print("The list contains", len(shape_list), "objects.")
                remove = int(input("Please select an item from 1 to " + str(len(shape_list)) + " to remove that object:"))

                del shape_list[remove - 1]

            else:
                print("The list contains no objects.")

        # Draw Shapes
        if menu == 4:
            turtle.hideturtle()
            turtle.setheading(0)
            for i in shape_list:
                if i.isCircle():
                    circle.draw(centerX, centerY, radius, color)
                elif i.isRectangle():
                    rectangle.draw(startX, startY, height, width, color)
            turtle.exitonclick()
        # Exit
        if menu == 5:
            playAgain = False

    print()
    print("Thank you for playing.")


main()
class Circle:

import turtle

class Circle:
    def __init__(self, centerX, centerY, radius, color, kind = "circle"):
        self.__centerX = centerX
        self.__centerY = centerY
        self.__radius = radius
        self.__color = color
        self.kind = "circle"

    def isCircle(self):
        if self.kind == "circle":
            return True

    def isRectangle(self):
        if self.kind == "circle":
            return False

    def draw(self, __centerX, __centerY, __radius, __color):
        turtle.penup()
        turtle.pencolor(__color)
        turtle.goto(__centerX, __centerY - __radius)
        turtle.pendown()
        turtle.fillcolor(__color)
        turtle.begin_fill()
        turtle.circle(__radius)
        turtle.penup()
        turtle.end_fill()
class Rectangle:

import turtle

class Rectangle:
    def __init__(self, startX, startY, height, width, color, kind):
        self.__startX = startX
        self.__startY = startY
        self.__height = height
        self.__width = width
        self.__color = color
        self.kind = "rectangle"

    def isRectangle(self):
        if self.kind == "rectangle":
            return True

    def isCircle(self):
        if self.kind == "rectangle":
            return False

    def draw(self, __startX, __startY, __height, __width, __color):
        turtle.penup()
        turtle.goto(__startX, __startY)
        turtle.pencolor(__color)
        turtle.fillcolor(__color)
        turtle.pendown()
        turtle.begin_fill()
        turtle.forward(__width)
        turtle.right(90)
        turtle.forward(__height)
        turtle.right(90)
        turtle.forward(__width)
        turtle.right(90)
        turtle.forward(__height)
        turtle.end_fill()
        turtle.penup()
The program appears to work. Turtle will draw the circular and rectangular shapes in their given location, but ALL of the shapes are drawn in the color of the shape that was last added to the list. Any ideas where I'm going wrong on color assignment?
Reply
#4
I'm not sure if this is the issue, but when you create the Circle or Rectangle classes, you store the details of the shape in various values: self.__startX, self.startY, and so on. But then when you draw them, you require the values to be passed to the draw method as parameters. I would just use the values you already stored. So line 22 of the rectangle class is turtle.goto(__startX, __startY). I would remove __startX and __startY from the parameter list of draw, and instead use turtle.goto(self.__startX, self.__startY). Then do the same for all of the other variables used in the draw method.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
Oooh! I was hopeful that would solve the problem (it made sense that it might...). I made the change:

class Circle:
import turtle

class Circle:
    def __init__(self, centerX, centerY, radius, color, kind = "circle"):
        self.__centerX = centerX
        self.__centerY = centerY
        self.__radius = radius
        self.__color = color
        self.kind = "circle"

    def isCircle(self):
        if self.kind == "circle":
            return True

    def isRectangle(self):
        if self.kind == "circle":
            return False

    def draw(self):
        turtle.penup()
        turtle.pencolor(self.__color)
        turtle.goto(self.__centerX, self.__centerY - self.__radius)
        turtle.pendown()
        turtle.fillcolor(self.__color)
        turtle.begin_fill()
        turtle.circle(self.__radius)
        turtle.penup()
        turtle.end_fill()
class Rectangle:

import turtle

class Rectangle:
    def __init__(self, startX, startY, height, width, color, kind):
        self.__startX = startX
        self.__startY = startY
        self.__height = height
        self.__width = width
        self.__color = color
        self.kind = "rectangle"

    def isRectangle(self):
        if self.kind == "rectangle":
            return True

    def isCircle(self):
        if self.kind == "rectangle":
            return False

    def draw(self):
        turtle.penup()
        turtle.goto(self.__startX, self.__startY)
        turtle.pencolor(self.__color)
        turtle.fillcolor(self.__color)
        turtle.pendown()
        turtle.begin_fill()
        turtle.forward(self.__width)
        turtle.right(90)
        turtle.forward(self.__height)
        turtle.right(90)
        turtle.forward(self.__width)
        turtle.right(90)
        turtle.forward(self.__height)
        turtle.end_fill()
        turtle.penup()
and changed the applicable section of my main code:

from circle import Circle
from rectangle import Rectangle
import turtle

def main():

    playAgain = True

    shape_list = []

    while playAgain:
        print("1) Enter Circle")
        print("2) Enter Rectangle")
        print("3) Remove Shape")
        print("4) Draw Shapes")
        print("5) Exit")
        menu = int(input("What would you like to do? "))

        color_list = ["red", "yellow", "blue", "green"]

        print(shape_list)

        # Enter Circle
        if menu == 1:
            centerX, centerY = eval(input("Enter the center position (x,y): "))
            radius = eval(input("Enter radius: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                    circle = Circle(centerX, centerY, radius, color, "circle")
                    shape_list.append(circle)
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False

        # Enter Rectangle
        if menu == 2:
            startX, startY = eval(input("Enter the starting position (x,y): "))
            height = eval(input("Enter height: "))
            width = eval(input("Enter width: "))

            correct = False
            while not correct:
                print("0) Red")
                print("1) Yellow")
                print("2) Blue")
                print("3) Green")
                color = eval(input("Choose a color: "))
                if color == 0 or color == 1 or color == 2 or color == 3:
                    color = color_list[color]
                    correct = True
                    rectangle = Rectangle(startX, startY, height, width, color, "rectangle")
                    shape_list.append(rectangle)
                else:
                    print("You have made an invalid selection.  Please try again.")
                    correct = False

        # Remove Shape
        if menu == 3:
            if len(shape_list) > 0:
                print(shape_list)
                print("The list contains", len(shape_list), "objects.")
                remove = int(input("Please select an item from 1 to " + str(len(shape_list)) + " to remove that object:"))

                del shape_list[remove - 1]

                print(shape_list)

            else:
                print("The list contains no objects.")

        # Draw Shapes
        if menu == 4:
            turtle.hideturtle()
            turtle.setheading(0)
            for i in shape_list:
                if i.isCircle():
                    circle.draw()
                elif i.isRectangle():
                    rectangle.draw()
            turtle.exitonclick()

        # Exit
        if menu == 5:
            playAgain = False

    print()
    print("Thank you for playing.")


main()
I am still running into the same issue where the color of the shape last added to the list is being used for every object. I also have just realized, as well, that the object is drawn in the position of the last object of that type's given position.

Any other ideas?
Reply
#6
This bit of code is your problem:

            for i in shape_list:
                if i.isCircle():
                    circle.draw()
                elif i.isRectangle():
                    rectangle.draw()
You want to draw i, but you are drawing circle. The circle variable is rewritten every time you enter a new circle, and then appended to shape_list. Also note that both Circle and Rectangle objects have a draw method, so you don't need to figure out what type of shape it is to draw it. Try this instead:

            for shape in shape_list:
                shape.draw()
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#7
you also don't need
def isCircle(self):
        if self.kind == "circle":
            return True
 
    def isRectangle(self):
        if self.kind == "circle":
            return False
and also
 def isRectangle(self):
        if self.kind == "rectangle":
            return True
 
    def isCircle(self):
        if self.kind == "rectangle":
            return False
nor .kind property
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
I must've misunderstood what you were telling me before, buran. I thought that testing the object type, somehow, using isCircle/isRectangle would solve my issue? I have removed it from both classes and removed the kind property, as well.

Also, I've changed
for i in shape_list:
    if i.isCircle():
        circle.draw()
    elif i.isRectangle():
        rectangle.draw()
to

for shape in shape_list:
    shape.draw()
as ichabod801 pointed out.

I also made a few minor tweaks (e.g. resetting the turtle screen each time user selects draw) and the code is now working as intended! Big Grin Yay! Thank you both for being so helpful (and thank you for explaining to me the reason for the issues with the way my code was written, too). Admittedly, I am an "older" student and worried that this (coding) might be beyond my grasp but I've found this forum (I've received assistance from both of you before) to be a major help.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  TypeError: __init__() missing 1 required positional argument: 'successor siki 1 4,302 Mar-08-2021, 02:05 PM
Last Post: Larz60+
  Missing 1 required positional argument in python code edwinostby 7 9,927 Jan-19-2021, 12:52 PM
Last Post: Serafim
  Missing positional arguments error?? hhydration 2 2,145 Oct-01-2020, 05:33 AM
Last Post: buran
  List of Objects print <__main. Problem Kol789 10 3,539 Jul-21-2020, 09:37 AM
Last Post: DeaD_EyE
  missing positional argument error programmert 1 2,819 Oct-18-2019, 11:05 AM
Last Post: Larz60+
  missing 1 required positional argument jedmond2 4 6,686 Sep-19-2019, 12:00 PM
Last Post: jefsummers
  missing 1 required positional argument mcgrim 10 19,753 May-07-2019, 09:02 PM
Last Post: Yoriz
  sorting a deck of cards (objects in a list) itmustbebunnies 1 7,202 Dec-05-2018, 02:44 AM
Last Post: ichabod801
  TypeError: method missing 1 positional argument koolinka 4 5,026 Nov-18-2018, 04:53 PM
Last Post: ichabod801
  Class positional argument error itmustbebunnies 2 2,995 Nov-07-2018, 11:09 AM
Last Post: stullis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020