我正在尝试实现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)
内爆炸,但我无法弄明白为什么。谢谢你的帮助!
答案 0 :(得分:2)
您应该非常小心__getattribute__
重载。
副作用是访问self.__class__
次来电__getattribute__
并创建虚拟redis查询。
当您使用新式课程时,您可能希望使用__getattr__
代替并避免无限递归问题,但如果您使用__getattr__
,则会返回对象属性之前如果您的实例中已存在此属性,则为redis值。
无论如何,只要你重载了__setattribute__
方法,你的对象就是不可变的,所以这不是一个大问题。
请参阅此SO回复,了解__getattr__
与__getattribute__
之间更详细的区别:Difference between __getattr__ vs __getattribute__