0

I'm new to creating classes and try to solve a problem/exercise.

When I try to instantiate the toolbox, I try to add some tools to it. My approach is to create it as a list, and append new elements to it. It returns a "None" type attribute, and I don't know how to fix it.

class Toolbox:
    def __init__(self):
        self.toolbox = []
    def add_tool(self, tool):
        self.toolbox.append(tool)
    def remove_tool(self, tool):
        self.toolbox.remove(tool)

class Hammers:
    color = ""
    def __init__(self, color=''):
        pass
    def hammer_in(self, nail):
        pass
    def remove(self, nail):
        pass
    def paint(self, color):
        pass

class Screwdrivers:
    size = 10
    def __init__(self, size=''):
        pass
    def tighten(self, screw):
        pass
    def loosen(self, screw):
        pass



toolbox = Toolbox()
hammer = Hammers()
screwdriver = Screwdrivers()

toolbox = toolbox.add_tool(hammer)
toolbox = toolbox.add_tool(screwdriver)


Output :

Traceback (most recent call last):
  File "C:Create Classes.py", line 133, in <module>
    toolbox = toolbox.add_tool(screwdriver)
AttributeError: 'NoneType' object has no attribute 'add_tool'

I'm trying to : Instantiate a toolbox, a screwdriver, and a hammer.

Put the hammer and screwdriver in the toolbox.

Thank you,

1
  • toolbox.add_tool returns None. You assign that to toolbox. Hence the error when you try to do toolbox.add_tool again. Just don't assign to toolbox Commented May 3, 2021 at 7:45

3 Answers 3

1

As Arseniy says, your problem comes from reassigning toolbox to a new object:

First, a Toolbox object is assigned to the toolbox reference

toolbox = Toolbox()

Then, the result of toolbox.add_tool, which is the object None is assigned to the toolbox reference, thus toolbox now no longer points to a instantiated Toolbox object:

toolbox = toolbox.add_tool(hammer) 

So, what you should do instead is simply remove the re-assignment:

toolbox.add_tool(hammer)
toolbox.add_tool(screwdriver)

And this should result in:

>>> print (toolbox.toolbox)
[<__main__.Hammers object at 0x...>, <__main__.Screwdrivers object at 0x...>]
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for this! So quick question - why does it return None? And I don't understand the result... Why does it not just result in a simple list?
Hi @m3.b. The issue here comes from how Python works internally. In Python everything is handled as an object (including non instantiated classes). So when you make reference assignments to a variable, what you are doing is assigning it an object. Thus, this assignment must always be possible. But what happens when you are not assigning anything in a variable assignment? Well, in fact that variable will reference the object None. Since the method toolbox.add_tool(hammer) does not have any return value, assigning it to toolbox will make toolbox reference the object None.
Hi @esocrats . Thanks for this comment. However, the add.tool() method has a function to append an element...doesn't it? Why would it return nothing? Or should I write return self.toolbox.append()instead?
Indeed, as long you do not write return [object] ([object] is a placeholder for the object you want to return) your method will return None. It might be useful for you to also take a look at the Python Typing module. Adding type hints to your functions, will help you keep track of what Python is (or should be) doing.
thank you. If I call >>> toolbox = Toolbox() >>> toolbox <__main__.Toolbox object at 0x0000025831C3DF70> . I do not understand this line : why does it not show me an empty list at this point?
|
1

add_tool return nothing (None), and you assign it to toolbox

toolbox = toolbox.add_tool(hammer)  <--- problem here 
toolbox = toolbox.add_tool(screwdriver)

So, toolbox become None and 'NoneType' object has no attribute 'add_tool'

Comments

0

add_tool and remove_tool return implicitly None. You should not assign this return value to toolbox.

You are using class-Attributes wrongly. color should be a instance attribute. The default value of size is wrong, since size is not a empty string.

The class Hammers represent one Hammer. Why can you paint with a hammer?

class Toolbox:
    def __init__(self):
        self.toolbox = []
    def add_tool(self, tool):
        self.toolbox.append(tool)
    def remove_tool(self, tool):
        self.toolbox.remove(tool)

class Hammer:
    def __init__(self, color=''):
        self.color = color
    def hammer_in(self, nail):
        pass
    def remove(self, nail):
        pass
    def paint(self, color):
        pass

class Screwdriver:
    def __init__(self, size=10):
        self.size = size
    def tighten(self, screw):
        pass
    def loosen(self, screw):
        pass


toolbox = Toolbox()
hammer = Hammer()
screwdriver = Screwdriver()
toolbox.add_tool(hammer)
toolbox.add_tool(screwdriver)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.