0

My dataclass has a field that holds an array of data in a custom type (actually it is a PyROOT std vector). However, for the user it is supposed to be visible as a list. This is simple enough with dataclass getters and setters, that convert the vector to list and vice versa. However, this works only if the user initialises the field with a full list. If the user wants to append to the list, it, obviously, doesn't work, as there is no permanent list associated with the field.

I wonder if there is a way to inhibit the ".append()" call on the field and call instead the vector's push_back()? Or perhaps there is a good Pythonic way to deal with it in general?

The context is, that I need the dataclass fields in the PyROOT format, as later I am storing the data in ROOT TTrees. However, I am creating this interface, so that the user does not need to know ROOT to use the dataclass. I know that I could create both the vector and the list that would hold the same data, but that seems like a waste of memory, and I am not certain how to update the vector each time the list is modified, anyway.

1 Answers1

0

According to the Python Docs, “Lists are mutable sequences, typically used to store collections of homogeneous items (where the precise degree of similarity will vary by application).” (emphasis added)

With that in mind, I would start off with something like this:

from collections.abc import MutableSequence


class ListLike(MutableSequence):
    def __init__(self):
        self.backing_data = object()  # Replace with the type your using


ListLike()

When you run that code, you’ll get the error: TypeError: Can't instantiate abstract class ListLike with abstract methods __delitem__, __getitem__, __len__, __setitem__, insert. Once you implement those methods, you’ll have have a type that acts a lot like list, but isn’t.

To make ListLikes act even more like lists, use this code to compare the two:

example_list = list()
example_list_like = ListLike()

list_attributes = [attribute for attribute in dir(example_list)]
list_like_attributes = [attribute for attribute in dir(example_list_like)]

for attribute in list_attributes:
    if attribute not in list_like_attributes:
        print(f"ListLikes don't have {attribute}")
print("-----------")
for attribute in list_like_attributes:
    if attribute not in list_attributes:
        print(f"lists don't have {attribute}")

and change your implementation accordingly.

Ginger Jesus
  • 95
  • 1
  • 2
  • 13
  • Thanks. Even before your answer, I've basically implemented my own list class that stores the data in the vector. The only problem with this approach is, that most likely the data is copied in assignment and read operations. Better solution would be to return a list that is a view of the vector, and for the vector to be a view of the list. The latter is impossible, because the vector is not my class. The former probably possible, but difficult. – Lech Wiktor Piotrowski Sep 13 '21 at 15:38