3

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)が爆破しますが、理由がわかりません。助けてくれてありがとう!

4

1 に答える 1

2

オーバーロードには細心の注意を払う必要があります__getattribute__

副作用は、self.__class__呼び出しにアクセス__getattribute__してダミーの redis クエリを作成することです。

__getattr__新しいスタイルのクラスを使用しているため、代わりに使用して無限再帰の問題を回避したい場合がありますが、使用すると、オブジェクト属性がインスタンスに既に存在する場合、redis 値の前__getattr__にオブジェクト属性が返されます。

とにかく、メソッドをオーバーロードしている限り、オブジェクトは一種の不変である__setattribute__ため、これは大きな問題ではありません。

と のより詳細な違いについては、この SO レスポンスを参照してください: __getattr____getattr____getattribute__ の違い__getattribute__

于 2013-03-05T14:46:14.717 に答える