使用__getattr__和__setattr__功能实现类似dict的对象 [英] Implementing a dict-like object with __getattr__ and __setattr__ functionality

查看:115
本文介绍了使用__getattr__和__setattr__功能实现类似dict的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现类似dict的对象,该对象可以通过__getattr____setattr__进行访问/修改,以方便用户使用.该类还实现了其他一些简单的功能.

I'm trying to implement a dict-like object which can be accessed/modified with __getattr__ and __setattr__ for ease of use for my users. The class also implements some other simple functionality.

使用此答案作为模板,我的实现当前如下:

Using this answer as a template, my implementation is currently as follows:

from collections import MutableMapping

class Dictish (MutableMapping):
    """
    A dict-like mapping object. vals are always coerced to str.
    Should provide __getattr__ and __setattr__ as aliases for
    __getitem__ and __setitem__.
    """
    def __init__ ( self, *args, **kwargs ):
        self.store = dict()
        self.update(dict(*args,**kwargs))

    def __getitem__ ( self, key : str ) -> str:
        return self.store[key]

    def __setitem__ ( self, key : str, val : str ) -> None:
        self.store[key] = str(val)

    def __delitem__ ( self, key : str ) -> None:
        del self.store[key]

    def __iter__ ( self ):
        return iter(self.store)

    def __len__ ( self ) -> int:
        return len(self.store)

    def __repr__ ( self ) -> str:
        return repr(self.store)

    # works fine by itself, but goes into infinite recursion
    # when __setattr__ is defined
    def __getattr__ ( self, attr : str ) -> str:
        return self.__getitem__(attr)

#    def __setattr__ ( self, attr : str, val : str ) -> None:
#        self.__setitem__(attr,val)

推荐答案

在编写问题并将其形式化时,我找到了答案(对我来说很常见).也许这可以帮助其他人.

As I was writing and formalizing the question, I found the answer (happens to me a lot). Maybe this can help someone else.

对我来说,解决方法如下:

The solution for me was the following:

def __getattr__ ( self, attr : str ) -> str:
    return self.__getitem__(attr)

def __setattr__ ( self, attr : str, val : str ) -> None:
    if attr == 'store':
        super().__setattr__(attr,val)
    else:
        self.__setitem__(attr,val)

关键是必须将store属性分离出来并从基类中调用,以避免递归.很简单,但我很容易错过!

The key is that the store attribute must be separated out and called from the base class to avoid recursion. Pretty simple but was easy for me to miss!

我添加了一些功能,用于添加您不想保留在store中的属性(即属性的通常含义).我也将store实现为OrderedDict,但这仅用于我的用例.显然,set_inst_attr例外是临时的/占位符.

I added functionality for adding attributes that you do not want to keep in store (ie. the usual meaning of attributes). I also implemented store as an OrderedDict, but this is just for my use-case. Obviously the set_inst_attr exception is temporary/a placeholder.

from collections import MutableMapping, OrderedDict

class ODictish (MutableMapping):
    """
    An OrderedDict-like mapping object.
    Provides __getattr__ and __setattr__ as aliases for __getitem__
    and __setitem__.
    Attributes which you do not want to keep in 'store' can be set with
    self.set_inst_attr.
    """
    def __init__ ( self , od=None):
        if od is None: od = OrderedDict()
        super().__setattr__('store', OrderedDict(od))

    def __getitem__ ( self, key ):
        return self.store[key]

    def __setitem__ ( self, key, val ):
        self.store[key] = val

    def __delitem__ ( self, key ):
        del self.store[key]

    def __iter__ ( self ):
        return iter(self.store)

    def __len__ ( self ):
        return len(self.store)

    def __repr__ ( self ):
        return repr(self.store)

    def __getattr__ ( self, attr ):
        if attr in vars(self):
            return vars(self)[attr]
        return self.__getitem__(attr)

    def __setattr__ ( self, attr, val ):
        if attr in vars(self):
            self.set_inst_attr(attr,val)
        else:
            self.__setitem__(attr,val)

    def set_inst_attr ( self, attr, val ):
        if attr == 'store':
            raise Exception("Don't do that.")
        super().__setattr__(attr,val)

    def move_to_end ( self, key, last=True ):
        self.store.move_to_end(key,last)

这篇关于使用__getattr__和__setattr__功能实现类似dict的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆