3

我正在尝试实现 redis 实际保存属性的类,但该类的用户不知道这一点(即跨多个客户端的对象持久性)。我知道有一些库为 python 包装了 redis,但没有一个库以这种简单的方式做到这一点(但如果我错了,请纠正我!)

__getattribute__我已经成功地实现了属性的自动 redis 存储,但如果没有无限递归将其炸毁,我似乎无法使用它进行检索。我想我在使用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)但我不知道为什么。谢谢你的帮助!

4

1 回答 1

2

你应该非常小心__getattribute__重载。

一个副作用是访问self.__class__调用__getattribute__并创建一个虚拟 redis 查询。

当您使用新式类时,您可能希望使用它__getattr__并避免无限递归问题,尽管如果您使用该属性,则如果该属性已存在于您的实例中,您将在 redis 值之前__getattr__返回对象属性。

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

__getattr__请参阅此 SO 响应以了解和之间的更详细区别__getattribute____getattr__ 与 __getattribute__ 之间的区别

于 2013-03-05T14:46:14.717 回答