0

The Goal
I am trying to create a practice script that stores a menu that can have new items added to it. The items are things like "battle animation", "text speed", or "subtitles". And the menu will print out all its items like this (notice the spacing for all items is adjusted to fit the largest one)

| border color |
| (black) blue red green |
| Text Speed |
| slow (medium) fast |
fig 1

My Methods
MenuItem itself is a class. It manages the contents of a menu item and stores how much adjustment space it needs when printing. This class works perfectly fine by itself. If the above two items were created and printed using the MenuItem class methods alone, they would look like this: | border color |
| (black) blue red green |
| Text Speed |
| slow (medium) fast |
fig 2

Menu is a class I made to store the menu items and to adjust their spacing values so they will print like fig 1.

My Code
This code was reduced to only show the reproducible error. The value lists(black,blue, red, green, etc) are not included.
#!/usr/bin/env python3

class Menu(object):
    class MenuItem(object):
        def __init__(self, propertyTitle):
            self.title = propertyTitle
            self.printsize = (len(self.title)+4)

        def printMenuItem(self):
            f_indent = 2;
            f_title = ((' '*f_indent)+ self.title.ljust(self.printsize-f_indent))
            print('|',f_title ,'|',sep='')

    def __init__(self):
        self.width = 0;
        self.items = [];

    def addItem(self, pTitle):
        f_menuItem = Menu.MenuItem(pTitle)
        if(f_menuItem.printsize < self.width):
        #if(f_menuItem.printsize < 5):
            #adjusting padding on the smaller new menu item
            f_menuItem.printsize = self.width
        elif(f_menuItem.printsize > self.width):
        #elif(f_menuItem.printsize > 5):
            #adjusting padding on all past menu items to fit this new big item
            self.width = f_menuItem
            for x in self.items:
                x.printsize = self.width
        self.items.append(f_menuItem)
    def printMenu(self):
        for x in self.items:
            x.printMenuItem()

print()

property_1_title = "border color";
property_2_title = "text speed";

myMenu = Menu()
#myMenu.items.append(myBorderColor)
#myMenu.items.append(myTextSpeed)
myMenu.addItem(property_1_title);
myMenu.addItem(property_2_title);
myMenu.printMenu()

The Problem
I am receiving the following errors:

line 20, in addItem
if(f_menuItem.printsize < self.width):
TypeError: '<' not supported between instances of 'int' and 'MenuItem'

line 24, in printMenuItem
f_title = ((' '*f_indent)+ self.f_title.ljust(self.printsize-f_indent))
TypeError: unsupported operand type(s) for -: 'MenuItem' and 'int'

For some reason python is interpretting the class attributes (which are ints) of MenuItem as class instances of MenuItem itself. At least that's how I interpretted the errors.
The weird part about this error is that this only happens when methods of the Menu class call MenuItem methods on the MenuItem instances it has stored internally.
As I mentioned before, these errors don't happen when the MenuItem class is the only class defined and used.
(also it doesn't matter if MenuItem is defined as a class within Menu or if it's defined as a seperate class before Menu. The same errors happen)

My question to you

Why is python interpretting f_menuItem.printsize and self.printsize as MenuItems instead of ints?
I can probably figure out a different way to structure the program to avoid this. But it's just a practice script. I just really want to know what is happening to create this error.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
wimworks
  • 283
  • 3
  • 15
  • 2
    `self.width = f_menuItem`? – user2357112 May 18 '18 at 02:15
  • You assign a `MenuItem` object to `self.width` explicitely. You even call the variable `f_menuItem`... `f_menuItem = Menu.MenuItem(pTitle)` then `self.width = f_menuItem`. As an aside, why would you use a nested class here? – juanpa.arrivillaga May 18 '18 at 03:00
  • @juanpa.arrivillaga `self.width = f_menuItem` was an uncompleted statement on my part. The class structure would make more sense if you saw the rest the attributes and methods the actual class has. I do admit the nested class looks silly in the code above. – wimworks May 18 '18 at 07:06

1 Answers1

2

Your problem is in addItem() specifically the elif branch of the if statement which contains the line:self.width = f_menuItem this corrupts self.width changing it from an int to a MenuItem in the first call of addIem. So when addItem is called a second time the comparison blows up.

Paula Thomas
  • 1,152
  • 1
  • 8
  • 13
  • Oh. Yeah you're right. I should have entered `self.width = f_menuItem.printsize`. I didn't notice that little mistake. – wimworks May 18 '18 at 07:00