可变@属性?

Mutable @property?

有没有办法在 Python 中定义 MUTABLE(不仅仅是可重新分配!)属性?我需要一个 属性,returns 文件中的一个列表,并在所述列表上使用 __setitem__ 时更改所述文件。


无效的示例:

>>> import mmap
>>> def someClass():
    def __init__(self, fileName):
        self.fileName = fileName

    @property
    def data(self):
        """Return data at start of eil in 4 byte chunks"""
        
        with open(self.fileName, mode = 'r+b') as f:
            with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as fmap:
                data = [fmap[i:i+4] for i in range(1024)]
        
        return data
    
    @data.setter
    def data(self, value):
        """Save data to file"""
        
        with open(self.fileName, mode = 'w+b') as f:
            with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_WRITE) as fmap:
                for i, data in enumerate(value):
                    fmap[i:i+4] = data

>>> a = someClass('C:\test.txt')
>>> a.data[0] == a.data[1]
False
>>> a.data[0] = a.data[1]
>>> a.data[0] == a.data[1]
False # Mutation did not register to file

我真的对 mmap 一无所知,所以我可能会弄乱那里的逻辑,但总体思路是一样的。
正如@jasonharper 在评论中所建议的那样,sulotion 是创建一个定义 __setitem__ 的自定义 class 并将其用于 someClass().data.

class FileUpdatingList:
    def __init__(self, filename):
        self.filename = filename

    def __getitem__(self, index):
        with open(self.fileName, mode = 'r+b') as f:
            with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as fmap:
                return fmap[index:index+4]
    
    def __setitem__(self, index, data):
        with open(self.fileName, mode = 'w+b') as f:
            with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_WRITE) as fmap:
                fmap[index:index+4] = data

现在的问题是 someClass().data = value 不再有效,您必须使用 someClass.data[:] = value。要解决这个问题,你可以写一个 属性 来为你做这个:

def someClass():
    def __init__(self, fileName):
        self.fileName = fileName
        self._data = FileUpdatingList(filename)

    @property
    def data(self):
        """Return data at start of eil in 4 byte chunks"""
        return self._data
    
    @data.setter
    def data(self, value):
        """Save data to file"""
        self._data[:] = value