5

I've read a thread on what a (non)subscriptable object is but it doesn't tell me what i can do about it.

I have a code calling a mypost private module. The aim is to set up mail accounts and to do this i create MailAccounts() objects defined in the mypost module. Quantity of accounts and their respective details are described in a configuration file. When the application starts, it collects account information and stores it in a dictionary, the structure of which is: accounts = {service : { <MailAccounts Object at xxxxx> : {username : myusername, password : mypassword}}} where service can be "gmail" and where MailAccounts is the class defined in the mypost module. So far so good. When however i want to setup the account, i need to call its method: MailAccounts.setupAccount(username, password). I do this by iterating each MailAccount object of the dictionary and ask to run the method:

for service in accounts:
        for account in accounts[service]:
            account.setupAccount(account['username'], account['password'])

But as you may have guessed it didn't work, Python returns:

TypeError: 'MailAccount' object is not subscriptable

If i create the same account manually however it works:

account = MailAccount()
account.setupAccount('myusername', 'mypassword')

Now i believe it has something to do with the fact that my <MailAccount Object at xxxx> is a dictionary key right? That makes it non-subscriptable (whatever that may mean)?

No what exactly does this mean to be non-subscriptable? What does it imply in this example? And of course: how can i solve / bypass this in this case?

Thanks, Benjamin :)

Community
  • 1
  • 1
neydroydrec
  • 6,973
  • 9
  • 57
  • 89

2 Answers2

5

The way to fix it is to use dictionaries properly.

for service in accounts:
        for account, creds in accounts[service].iteritems():
            account.setupAccount(creds['username'], creds['password'])
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Thanks. I understand the code you propose, but i don't really understand what difference it really makes to Python? Could you explain please? – neydroydrec May 12 '11 at 11:27
  • If you want the technical explanation, then a "subscriptable object" is one whose class defines one or more of the `__getitem__()`, `__setitem__()`, and `__delitem__()` methods. http://docs.python.org/reference/datamodel.html#emulating-container-types – Ignacio Vazquez-Abrams May 12 '11 at 11:29
  • 1
    @Benjamin: Always use `iterkeys`, `itervalues` and `iteritems` explicitly and you'll avoid confusion as to what you're getting from the dict. In your original code, `account` is a MailAccount instance (a key), not a dict (a value). – Cat Plus Plus May 12 '11 at 11:32
  • @Cat Plus Plus: Oh, i see! So the problem is not the method but what object i request the method from or what i feed to the method :) – neydroydrec May 12 '11 at 11:36
0

The problem is that when you iterate over a dictionary, you get the keys of that dictionary, not the items.

>>> x = { 'a': 1, 'b': 2 }
>>> for item in x:
...     print(item)
... 
a
b

If you want to iterate over the values, do this:

>>> for item in x.values():
...     print(item)
... 
1
2

There is also an items method, for both keys and values at the same time:

>>> for item in x.items():
...     print(item)
... 
('a', 1)
('b', 2)
Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415