1

I am writing a simple Python class named "Bag":

class Bag:
def __init__(self, items=None):
    if self.items == None:
        self.items = defaultdict()
    else:
        temp_dict = defaultdict()
        for key in self.items:
            temp_dict[key] += 1
        self.items = temp_dict 

The variable items takes in a list of objects, such as:

['d','a','b','d','c','b','d']

From there, "def __init__(self, items=None)" will either:

  1. Initialize items as an empty defaultdict, if nothing was passed into items, or
  2. Initialize the passed in argument, if a list of objects were passed into items.

For example, this should work:

b = Bag()

The absence of an argument should be fine, as items is set, by default, to _None.

However, this always raises an exception(from a script that checks for errors):

*Error: b = Bag() raised exception AttributeError: 'Bag' object has no attribute 'items'

I want to initialize Bag() without putting a passing an argument into items.

Hope everything is clear, tell me if it isn't.

Any ideas or anything wrong with the code?

5
  • 3
    I think you can do def __init__(self, items=None): which will still allow items to optionally be set when you want it to be set Commented Apr 22, 2017 at 2:16
  • @downshift I made the changes you've suggested, but it still gives me the same exception. Commented Apr 22, 2017 at 2:21
  • my apologies, put self.items = items as the first line after def __init__(.. Commented Apr 22, 2017 at 2:25
  • Did you notice that you started comparing self.items before even defining it? Your error is that if coming before the assignation Commented Apr 22, 2017 at 2:48
  • 1
    @monchitos82 Yeah, I noticed that from labheshr's solution. Commented Apr 22, 2017 at 2:54

2 Answers 2

2
from collections import defaultdict

class Bag(object):

def __init__(self, items=None):
    self.items = items or list()
    if not self.items:
        self.items = defaultdict()
    else:
        temp_dict = defaultdict()
        for key in self.items:
            temp_dict[key] += 1
        self.items = temp_dict

I made a few corrections:

1) create self.items and initialize with items 2) compare with None using is None , or simply not self.items, since empty lists evaluate to False

Sign up to request clarification or add additional context in comments.

3 Comments

Beware of the mutable default. stackoverflow.com/questions/1132941/…
Please never use a mutable value as a default for an argument. It is cerated a t function creation time and shared across invocations, so if your function happens to update items, the next call will see it. Use None as default, then use items or [] (or iems or defaultdict(int) in your case) when accessing it.
@labheshr Thank you! I made the changes, and it worked. I realized that I never initialized self.items before the if-else statement.
2

'Bag' object has no attribute 'items' means: somewhere in the Bag's method you're accessing self.items that has not been defined.

And indeed you do. In the constructor, you write: if self.items == None: before you make the first assignment to self.items, thus creating it.

I think it's a typo, and you meant if items is None:, referring to the parameter.

This code can be simplified, though. My take:

import collections  # Batteries included.

...
def __init__(self, items=None):
    if not items:  # Covers both None and empty list.
        self.items = {}
    else:
        self.items = collections.Counter(items)

This can be simplified even more:

     ...
     self.items = collections.Counter(items or [])

If you strictly want a to use a defaultdict, you can:

     self.items = collections.defauldict(int, collections.Counter(items or []))

(Note that defaultdict() without an argument makes rather little sense.)

3 Comments

Thanks for the suggestion. I would love to use Counter, but, sadly, the project I'm working on requires using "defaultdict".
Taking out the extra suggestion this solves your question without "altering" your initial code
Updated my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.