开发者

Python "generic" class property encode/decode

I almost guarantee this is something simple. I am trying to create a generic property to wrap a django text/blob field. This isn't Django specific, its really just an issue with design. I have some class level variables and am using a pseudo delegate to be able to reuse an decode method.

class DBTable(models.Model):
  class Meta:
     db_table="some_table"

  def set_data(self, data):
     att = self.__getattribute__(data.__name__)
     att = base64.encodestring(data)

  def get_data(self,prop):
     def func(self):
         att = self.__开发者_JAVA技巧getattribute__(prop)
         return base64.decodestring(att)
     return func

  #issue is here, i need to pass self to get_data
  blob_a = property(get_data("blob_a"), set_data)
  blob_b = property(get_data('blob_b'), set_data)

And the issue comes on the above two lines, I need to pass self. I have tried using the class but its not recognized.


It was simple, the problem above was fixed by pulling it out, and below is the final working solution.

def encode_data(self, data):
     def func(self,data):
        self.__setattr__(prop, base64.encodestring(data))
     return func

def decode_data(self,prop):
     def func(self):
         att = self.__getattribute__(prop)
         return base64.decodestring(att)
     return func


class DBTable(models.Model):
  class Meta:
     db_table="some_table"

  blob_a = property(decode_data("_blob_a"), encode_data("_blob_a"))
  blob_b = property(decode_data('_blob_b'), encode_data("_blob_b"))

  _blob_a = models.TextField(
        db_column='blob_a',
        blank=True)
  _blob_b = models.TextField(
        db_column='blob_b',
        blank=True)


Simply remove self from get_data and make it a function outside the class.

get_data_factory("blob_a") will return a function, which expects self as an argument. That is perfectly fine. It does not have to receive (in fact, it should not receive) that value from get_data.

def get_data_factory(prop):
    def get_data(self):
        return base64.decodestring(getattr(self,prop))
    return get_data

class DBTable(models.Model):
    ...
    blob_a = property(get_data_factory("blob_a"), set_data)

Regarding the final solution: I think there is a problem with the call signature of encode_data and decode_data. Perhaps you meant:

def encode_data(prop):
     def func(self,data):
        setattr(self,prop, base64.encodestring(data))
     return func

def decode_data(prop):
     def func(self):
         return base64.decodestring(getattr(self,prop))
     return func


Use def get_data(prop): - only your inner function should accept self as the outer one is not executed as an instance method.


You could do this with lambda:

blob_a = property(lambda s: s.get_data('blob_a'), lambda s: s.set_data('blob_a'))
blob_b = property(lambda s: s.get_data('blob_b'), lambda s: s.set_data('blob_b'))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜