如何使一个类的函数类似于嵌套字典?

4

我的目标

我正在尝试创建一个可以存储和操作多个数据集的类。

然而,我在尝试让访问数据变得尽可能简单和直观时遇到了一些问题。该对象的布局实质上就像一个嵌套字典,其布局看起来如下:

data = { "File1_Column1": {'header': [...],
                           'data':   [...]},
         "File1_Column2": {'header': [...],
                           'data':   [...]}, ...}

我希望发生的事情

假设我有一个名为data的这个类的实例,我希望data['File1_Column1']['header']data['File1_Column1']['data']能够返回人们所期望的内容,但我也希望data['File1_Column1']能够返回与data['File1_Column1']['data']相同的结果。我之所以这样做是因为我可以预见到自己99%的时间会使用数据列表,这将使其更加方便。

前两个问题非常简单,只需利用__getitem__即可解决,然而,我真正困扰的是如何让后者起作用。

下面是我简化后的代码。我尝试了在Data类的__getitem__方法中使用if语句来检查Subscript类的__getitem__方法是否被调用,但没有成功。

我已经尝试过的

class Data:

    def __init__(self):
        self._data = {}

    def append(self, label, data):
        self._data[label] = data

    def __getitem__(self, label):

        class Subscript:

            def __init__(self, data):
                self._data = data

            def __getitem__(self, label):
                return self._data[label]

        subdata = Subscript(self._data[label])
        return subdata

data = Data()
example = {'header': ['Trace', 'Unit'], 'data': [1, 2, 3, 4]}
data.append('Label', example)
print(data['Label'])
print(data['Label']['data'])
print(data['Label']['header'])

结果

<__main__.Data.__getitem__.<locals>.Subscript object at 0x007B4B10>
[1, 2, 3, 4]
['Trace', 'Unit']

我期望发生的事情

[1, 2, 3, 4]
[1, 2, 3, 4]
['Trace', 'Unit']

有没有一种方法可以实现这个?

你希望如何区分在对象中调用列(data['File1_Column1'])和调用列中的数据(data['File1_Column1'][index])? - user10417531
7
不要认为这是可能的。你期望data['Label']根据后面的内容评估出Subscript或者[1,2,3,4]中的一个。由于Python无法看到未来,因此这是不可能的。 - rdas
我已经想到了这种情况,但我希望有些我没有看到的东西。谢谢! - jakebrehm
2个回答

0

也许你可以使用两个字典来存储不同的项目:

headers= { "File1_Column1": ...,
            "File1_Column2": ...
            },

data  = {"File1_Column1": ..., 
          "File1_Column2": ...}

-1

可以使用repr方法来实现这一点。

您可以为Subscript类添加一个repr方法。

def __repr__(self):
    return str(self._data['data'])

这里是带有repr方法和一个额外示例的代码 -

class Data:

    def __init__(self):
        self._data = {}

    def append(self, label, data):
        self._data[label] = data

    def __getitem__(self, label):


        class Subscript:

            def __init__(self, data):
                self._data = data
                self.label = label

            def __getitem__(self, label):
                self.label = label
                return self._data[label]

            def __repr__(self):
                return str(self._data['data'])

        subdata = Subscript(self._data[label])
        return subdata

data = Data()
example = {'header': ['Trace', 'Unit'], 'data': [1, 2, 3, 4]}
example2 = {'header': ['Trace2', 'Unit2'], 'data': [11, 22, 33, 42]}
data.append('Label', example)
data.append('Label2', example2)
print(data['Label'])
print(data['Label']['data'])
print(data['Label']['header'])
print(data['Label2'])
print(data['Label2']['data'])
print(data['Label2']['header'])

结果(预期发生的事情)-

Shreyashs-MacBook-Pro:~ shreyash$ python test.py 
[1, 2, 3, 4]
[1, 2, 3, 4]
['Trace', 'Unit']
[11, 22, 33, 42]
[11, 22, 33, 42]
['Trace2', 'Unit2']

那只是改变了对象的外观,而不是它实际上的本质。你把你的对象放在一个小列表装扮中,但是如果试图像它看起来的列表一样使用它,它将完全失败。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接