Inhibiting a method called on a dataclass member

189 Views Asked by At

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

There are 1 best solutions below

1
On BEST ANSWER

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.