自动redis查找python对象

时间:2013-02-10 00:13:51

标签: python object redis getattribute

我正在尝试实现redis实际拥有属性的类,但是类的用户并不知道这个(即跨多个客户端的对象持久性)。我知道有一些libs为python包装redis但是没有一个以这种简单的方式完成这个(但如果我错了就请纠正我!)

我已经成功实现了属性的自动redis存储,但是我似乎无法使用__getattribute__进行检索而无法进行无限递归。我认为我在使用object.__getattribute__等方面要小心,但显然我必须遗漏一些东西:

class redisStored(object):
    global redis

    # A class method to implement object retrieval from redis
    # Call <Classname>.load(<id>) to create a new instance which exists in redis
    @classmethod
    def load(cls,id):
        # Create the object
        obj = cls.__new__(cls)
        # Set id without calling obj's __setattr__
        object.__setattr__(obj,'id',int(id))
        # Return the object we created
        return obj

    def __str__(self):
        # Return "<ClassName>:<id>" to differentiate ids in redis
        # You can use this to say redis.hgetall(g) where g is the instance

        return "%s:%s" % (self.__class__.__name__, str(object.__getattribute__(self,'id')))
        #                                     self.id here ^ would cause infinite recursion

    # This works fine
    def __setattr__(self,name,value):
        redis.hset(self,name,value)
        return object.__setattr__(self,name,value)

    # This blows up with infinite recursion, WHY??
    def __getattribute__(self,name):
        _val = redis.hget(self,name)
        if not _val:
            return object.__getattribute__(self,name)
        else:
            return _val

如果我追踪它,它会在_val = redis.hget(self,name)内爆炸,但我无法弄明白为什么。谢谢你的帮助!

1 个答案:

答案 0 :(得分:2)

您应该非常小心__getattribute__重载。

副作用是访问self.__class__次来电__getattribute__并创建虚拟redis查询。

当您使用新式课程时,您可能希望使用__getattr__代替并避免无限递归问题,但如果您使用__getattr__,则会返回对象属性之前如果您的实例中已存在此属性,则为redis值。

无论如何,只要你重载了__setattribute__方法,你的对象就是不可变的,所以这不是一个大问题。

请参阅此SO回复,了解__getattr____getattribute__之间更详细的区别:Difference between __getattr__ vs __getattribute__