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 optp开发者_如何学编程arse library and it returns an object accessible like that.
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__
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.
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
name.attribute
is object access in Python, not dict access
__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.
精彩评论