Python“泛型”类属性编码/解码

2 投票
3 回答
780 浏览
提问于 2025-04-16 16:26

我几乎可以保证这只是个简单的问题。我想创建一个通用的属性,用来包装Django的文本或二进制字段。这其实不是Django特有的问题,更多的是设计上的问题。我有一些类级别的变量,并且使用了一个伪委托,以便能够重用一个解码的方法。

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.__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)

问题出在上面的两行代码,我需要传递self(指代当前对象)。我尝试过使用类,但没有被识别。


其实很简单,上面的问题通过把它提取出来解决了,下面是最终的可用解决方案。

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)

3 个回答

0

你可以用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'))
1

使用 def get_data(prop): 这个写法 - 只有你内部的函数需要接受 self,因为外部的函数并不是作为实例方法来执行的。

3

简单来说,把 selfget_data 中去掉,然后把它放到类外面作为一个普通函数。

get_data_factory("blob_a") 会返回一个函数,这个函数需要 self 作为参数。这是完全可以的。它不需要从 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)

关于最后的解决方案:我觉得 encode_datadecode_data 的调用方式有问题。也许你想表达的是:

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

撰写回答