2013-12-13 4 views
0

Я пытаюсь реализовать обертку вокруг базы данных redis, которая выполняет некоторую бухгалтерию, и я подумал об использовании дескрипторов. У меня есть объект с кучей полей: рамки, сбои и т. Д., И мне нужно иметь возможность получить, и при необходимости увеличивать поле. Я пытался реализовать дескриптор Int-Like:Способы дескрипторов

class IntType(object): 
    def __get__(self,instance,owner): 
     # issue a GET database command 
     return db.get(my_val) 

    def __set__(self,instance,val): 
     # issue a SET database command 
     db.set(instance.name,val) 

    def increment(self,instance,count): 
     # issue an INCRBY database command 
     db.hincrby(instance.name,count) 

class Stream: 
    _prefix = 'stream' 
    frames = IntType() 
    failures = IntType() 
    uuid = StringType() 

s = Stream() 

s.frames.increment(1) # float' object has no attribute 'increment' 

Is кажется, что я не могу получить доступ к инкременту() метод в моем дескрипторе. У меня не может быть указателя в объекте, возвращаемом __get__. Для этого потребуется дополнительный db-запрос, если все, что я хочу сделать, - это увеличение! Я также не хочу increment() в классе Stream, так как позже, когда я хочу иметь дополнительные поля, такие как строки или множества в Stream, тогда мне нужно будет набрать check heck из всего.

ответ

0

Это работает?

class Stream: 
    _prefix = 'stream' 

    def __init__(self): 
     self.frames = IntType() 
     self.failures = IntType() 
     self.uuid = StringType() 
+0

Я не думаю, что это решает ничего. – proteneer

0

Попробуйте это:

class IntType(object): 
    def __get__(self,instance,owner): 
     class IntValue(): 

      def increment(self,count): 
       # issue an INCRBY database command 
       db.hincrby(self.name,count) 

      def getValue(self): 
       # issue a GET database command 
       return db.get(my_val) 

     return IntValue() 

    def __set__(self,instance,val): 
     # issue a SET database command 
     db.set(instance.name,val) 
+0

Вызов приращения все еще приводит к двум запросам: db.get и db.hincrby – proteneer

+0

Хорошо, я исправлю это –

+0

, если мне нужно явно добавить getValue(), тогда это почти победит цель использования дескрипторов для начала. – proteneer

0

Почему бы не определить магический метод iadd, а также получить и набор. Это позволит вам выполнять нормальное добавление с назначением в классе. Это также означает, что вы можете обрабатывать приращение отдельно от функции get и тем самым минимизировать доступ к базе данных.

Меняем:

def increment(self,instance,count): 
     # issue an INCRBY database command 
     db.hincrby(instance.name,count) 

к:

def __iadd__(self,other): 
     # your code goes here 
+0

Это было бы неплохо, но это одноразовое решение. Приращение - это атомная операция, и это не совсем дополнение. Скажем позже, я хочу добавить SetType с помощью таких методов, как set_add, set_intersect и т. Д. Для этих типов нет соответствующих встроенных элементов. – proteneer

+0

Так что, чтобы быть ясным, причина, по которой инкремент не работает в вашем ориджинном коде, заключается в том, что вы реализовали метод get magic, и поэтому, когда вы пытаетесь разыменовать свой объект, чтобы вызвать приращение, вы вместо этого вызываете get и получаете его результат, а не сам объект. Следовательно, резонанс, который вы видите, жалуется, что float не имеет метода приращения. Похоже, что очень конкретный и узкий интерфейс, заданный дескриптором, не то, что вам действительно нужно здесь. Если это так, тогда вам нужно остановить перегрузку и использовать разные имена для функций get и set. – Tommy

Смежные вопросы