dwitvliet
dwitvliet

Reputation: 7671

Giving 'NoneType' object attributes

Is it possible to assign attributes to the 'Nonetype' object to tell Python what to do if they are called?

Here is my problem:

I have a class that functions as a library to store instances of myOtherObject. Before adding an instance, it first checks if that key already exists and then appends the data to the instance assigned to that key rather than overwriting it.

class MyClass:

    def __init__(self):
        self.myLibrary = {}

    def __setitem__(self, key, item):
        if key not in self.myLibrary:
            self.myLibrary[key] = myOtherObject(name=item[0], attr1=[item[1]], attr2=[item[2]])
        else:
            self.myLibrary[key].attr1.append(item[1])
            self.myLibrary[key].attr2.append(item[2])

    def __getitem__(self, key):
        if key in self.myLibrary:
            return self.myLibrary[key]
        else:
            return None #???

When retrieving data from the library it should check if the key exists too, and only return the assigned object if the key exists. This works fine or calling just the object, however not when calling the attributes of that object:

>>> o = MyClass()
>>> o['key1'] = ['name1','b','c']
>>> o['key1']
<__main__.myOtherObject instance at 0x05509B48>
>>> o['key1'].attr1
'b'
>>> o['key2']
>>> o['key2'].attr1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'attr1'

Can I somehow tell Python not to do anything and just return None when attributes attr1 and attr2 are called from the 'NoneType' object?

Upvotes: 0

Views: 2434

Answers (3)

Keith
Keith

Reputation: 43054

That's probably the wrong question to ask. The proper (pythonic) thing to do there in the __getitem__ method is to raise KeyError exception. Then you handle that exception in the caller, or higher up in an appropriate place that can deal with it.

Upvotes: 0

Marcin
Marcin

Reputation: 49866

Is it possible to assign attributes to the 'Nonetype' object

No.

>>> o = None
>>> o.foo = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'foo'
>>> setattr(o,'foo',1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'foo'
>>> getattr(o,'foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'foo'

Before adding an instance, it first checks if that key already exists and then appends the data to the instance assigned to that key rather than overwriting it.

This is a classic use case for a defaultdict:

import collections
d = collections.defaultdict(list)
d['foo'].append(1)
print d #=> defaultdict(<type 'list'>, {'foo': [1]})

When retrieving data from the library it should check if the key exists too, and only return the assigned object if the key exists. This works fine or calling just the object, however not when calling the attributes of that object:

OK. What do you want to happen when the key does not exist?

Can I somehow tell Python not to do anything and just return None when attributes attr1 and attr2 are called from the 'NoneType' object?

What does this mean? If you attempt to access an attribute which does not exist, you get an exception, as above. The solution would be to handle the exception, and return None; but it would be much better to let the exception propagate, because None is not a valid input.


In summary, everything you want can be achieved with a defaultdict. Probably don't create your own class.

Upvotes: 1

Thomas Orozco
Thomas Orozco

Reputation: 55263

Use getattr:

>>> o = None
>>> print getattr(o, "attr1", None)
None

Upvotes: 0

Related Questions