fent
fent

Reputation: 18205

How do you make an access a hash in python?

I know this question sounds very basic. But I can't find it using Google. I know that there are dictionaries that look like

o = {
  'a': 'b'
}

and they're accessed with o['a']. But what are the ones that are accessed as o.a called? I know they exist because I'm using optparse library and it returns an object accessible like that.

Upvotes: 2

Views: 158

Answers (5)

Ethan Furman
Ethan Furman

Reputation: 69190

__getattr__ is the method you want to implement, along with __setattr__. Here is a very simplistic example (no error checking, etc) that shows an object which allows both dictionary-style and attribute-style access:

Missing = object()

class AttrElem(object):
    def __init__(self, **kwds):
        self.items = kwds.copy()
    def __getitem__(self, name):
        result = self.items.get(name, Missing)
        if result is not Missing:
            return result
        raise KeyError("key %r not found" % name)
    def __setitem__(self, name, value):
        self.items[name] = value
    def __getattr__(self, name):
        result = self.items.get(name, Missing)
        if result is not Missing:
            return result
        raise AttributeError("attribute %r not found" % name)
    def __setattr__(self, name, value):
        if name == 'items':
            object.__setattr__(self, name, value)
        else:
            self.items[name] = value
    def __repr__(self):
        return 'AttrElem(%s)' % ', '.join(
                ["%s:%s" % (k, v) for k, v in self.items.items()]
                )

In use it looks like this:

example = AttrElem(this=7, that=9)
print(example)
example.those = 'these'
example['who'] = 'Guido'
print(example)

As you can see from the code __getitem__ and __getattr__ are both very similary, differing only in the exception that gets raised when the target cannot be found.

Upvotes: 0

Garrett Berg
Garrett Berg

Reputation: 2635

You can access the variables as a dictionary in "new style classes". I think you have to be a little careful though.

>>> class C(object): # python 2 code, inheriting from 'object' is automatic in 3
    a = 5
    def __init__(self):
        self.j = 90


>>> c = C()
>>> c.__dict__
{'j': 90}
>>> print c.j
90
>>> print c.a
5

notice that 'j' showed up in the dictionary and 'a' didn't. It looks to have something to do with how they are initialized. I'm a little confused by that behavior and wouldn't mind an explanation from a guru :D

Edit:

Doing a little more playing, it is apparent why they decided to go with the behavior above (but it is still a little strange

>>> class C(object):
    a = 5
    def __init__(self):
        self.j = 90
        self.funct = range # assigning a variable to a function

>>> c = C()
>>> c.__dict__
{'j': 90, 'funct': <built-in function range>}

I think it separates the class object (which would be the same for every class) with new class members (such as those initiated inside init). If I now do

>>> c.newvar = 234
>>> c.__dict__
{'j': 90, 'newvar': 234, 'funct': <built-in function range>}

You can see it is building a dictionary! Hopefully this helps :D

Upvotes: 1

geekosaur
geekosaur

Reputation: 61449

Looks to me like optparse simulates an attribute interface to a hidden dict, but there's a standard library that does something sort of similar, if not really a dictionary: collections.namedtuple. I can't speak to the other mechanisms presented here.

Upvotes: 1

user2665694
user2665694

Reputation:

You can not access dicts using the '.' unless you implement your own dict type by deriving from dict and providing access through the '.' notation by implementing the __getattribute__() API which is in charge for performing attribute style access.

See http://docs.python.org/reference/datamodel.html#object.__getattribute__

Upvotes: 2

Eli Bendersky
Eli Bendersky

Reputation: 273686

name.attribute is object access in Python, not dict access

Upvotes: 0

Related Questions