Ruby Mash equivalent in Python?
in Ruby, there's this awesome library called a Mash which is a Hash but through clever use of missing_method can convert:
object['property']
to
object.property
开发者_StackOverflow中文版This is really useful for mocks. Anyone know of a similar kind of thing in Python?
Is it absolutely necessary that you base this on a dict? Python objects can dynamically acquire attributes with very little extra plumbing:
>>> class C(object): pass
...
>>> z = C()
>>> z.blah = "xyzzy"
>>> dir(z)
['__class__', '__delattr__', '__dict__', ... '__weakref__', 'blah']
Is __getitem__
what you're looking for?
class C:
def __init__(self):
self.my_property = "Hello"
def __getitem__(self, name):
return getattr(self, name)
c = C()
print c['my_property'] # Prints "Hello"
or are you looking for the reverse of that, via__getattr__
?
class D(dict):
def __getattr__(self, name):
return self[name]
d = D()
d['x'] = "Hello"
print d.x # Prints "Hello"
(Edit: As Paul McGuire kindly points out in the comments, this code only demonstrates the bare bones of a full solution.)
Is it absolutely necessary that you base this on a dict?
Yes if you then want to treat it as a list of items, without abusing __dict__
.
The following is my old answer to the Mash question. It provides a default, the default may be a method or an object, if it's an object it will clone deeply (not just hot-link) if it's used more than once.
And it exposes its simple key values as .key
:
def Map(*args, **kwargs):
value = kwargs.get('_default', None)
if kwargs.has_key('_default'): del kwargs['_default']
# CONSIDER You may want to look at the collections.defaultdict class.
# It takes in a factory function for default values.
#
# You can also implement your class by overriding the __missing__ method
# of the dict class, rather than overriding the __getitem__.
#
# Both were added in Python 2.5 according to the documentation.
class _DefMap(dict):
'But CONSIDER http://pypi.python.org/pypi/bunch/1.0.0 '
def __init__(self, *a, **kw):
dict.__init__(self, *a, **kw)
self.__dict__ = self
def __getitem__(self, key):
if not self.has_key(key):
if hasattr(value, '__call__'):
self[key] = value(key)
else:
self[key] = copy.deepcopy(value)
return dict.__getitem__(self, key)
return _DefMap(*args, **kwargs)
Look here https://pypi.python.org/pypi/mash . Also you can convert dict to mash object.
精彩评论