Python中的Ruby Mash等价物是什么?

4

在Ruby中,有一个很棒的库叫做Mash,它是一个Hash,但通过巧妙地使用missing_method可以进行转换:

object['property']

object.property

这对于模拟非常有用。有人知道Python中类似的东西吗?

4个回答

7

你是否非常必须基于字典来完成这个任务呢?Python对象可以动态地获取属性,而无需太多额外的工作:

>>> class C(object): pass
...
>>> z = C()
>>> z.blah = "xyzzy"
>>> dir(z)
['__class__', '__delattr__', '__dict__', ... '__weakref__', 'blah']

哇,太棒了,谢谢!我很愿意为这么快的回答再加分 :) - Julian H

4
你是否在寻找 __getitem__ 方法?
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"

或者你是在寻找相反的方法,通过__getattr__实现吗?

class D(dict):
   def __getattr__(self, name):
      return self[name]

d = D()
d['x'] = "Hello"
print d.x  # Prints "Hello"

(编辑:正如Paul McGuire在评论中指出的那样,此代码仅演示了完整解决方案的基本框架。)

为了更完整地模拟属性,请实现 __dir__ 方法以返回所有字典属性和所有用户指定的名称。 - PaulMcG
由于 __getattr__ 只有在没有找到属性时才会被调用,所以会与字典自身的属性(如 items、values 等)产生冲突。因此,可以设置 d['items'],但无法通过此 __getattr__ 获取该属性。为了解决这个问题,应编写 D 来包含并委托给一个字典,而不是从 dict 继承。 - PaulMcG
最后,OP正在尝试编写模拟对象,因此__setattr__可能会在某个时候出现在画面中,以便可以编写和读取x.xyzzy - PaulMcG

1
这个一定要基于字典吗?如果你想将其作为项目列表处理,而不滥用 __dict__,那么是的。
以下是我对 Mash 问题的旧回答。它提供了一个默认值,该默认值可以是方法或对象,如果它是一个对象,当它被多次使用时,它会进行深度克隆(而不仅仅是热链接)。
并且它将简单的键值暴露为 .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)

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接