2013-02-10 56 views
3

我试图实现哪些redis实际上拥有属性的类,但类的用户不知道这一点(即跨多个客户端的对象持久性)。我知道有几个libs将python包装为redis,但没有一个以这种简单的方式完成此操作(但是请纠正我,如果我错了!)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)但我想不出为什么。谢谢你的帮助!

+0

没有更详细的“它吹起来”,恐怕我们真的不能用它为什么做它帮助。 – 2013-03-02 19:53:25

+0

对不起 - 更具体地说,由于redis.hget(self,name)中的无限递归而炸毁了它。所以在hget里面的某个地方,它正在调用同一个对象上的getattr,这就是我无法弄清的。或者我误解了getattr的情况? – Fiskabollen 2013-03-06 16:20:44

回答

2

你应该非常仔细地用__getattribute__重载。

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

当您正在使用新的样式类,你可能需要使用__getattr__代替,避免无限递归问题,但如果你使用__getattr__将返回对象属性以前此属性是否在您的实例已经存在Redis的价值。

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

请参考__getattr____getattribute__之间更详细的区别这个SO回应:Difference between __getattr__ vs __getattribute__

+0

感谢您的帮助。 '_getattr__'没有解决我的问题,因为我需要来自redis的属性(以防其他事件更新)。我认为更好的方法是创建一个'get('')'方法 - 这样,显然我们可以从redis中获得一个值,而不是将它隐藏在普通的类功能之后。 – Fiskabollen 2013-04-03 14:09:49