5
\$\begingroup\$

As you probably know, Python slices like arr[1:3] etc. do NOT provide a view onto list and instead creates a copy of the list, what can be not optimal performance if array is big and you make for example arr[1:] (copies all exept first) the idea of a view to an array is like :

class ylist_view():

    def __init__(self,lst, begin, end):

        self.list = lst
        self.len = end - begin
        self.begin = begin
        self.end = end

    def __getitem__(self, i):
        if i<0: i += self.len
        return self.list[self.begin + i]

    def __setitem__(self, i,value):
        if i<0: i += self.len
        self.list[self.begin + i] = value    

     def __str__(self):
            return  '[' + ', '.join( str(self.list[i]) for i in range(self.begin, self.end)) + ']'



class inbox():

    def __init__(self, value):
        self.value = value

    def __str__(self):
        return '<' + str(self.value) + '>'

    def __repr__(self):
        return '<' + str(self.value) + '>'

    a =   [ inbox(x) for x in  [1,2,3,4,5]]

    b = a [1:3]

    b[0] = 20 # creates a copy

    print('list a is unchanged:', a)
    print('b = a [1:3] is a copy of a :', b)        

    c = ylist_view(a,1,3)

    c[0] = 20

    print('ylist_view c is a view to a:', a)

Inbox class is a dummy class for illustration. As you can see, b = a [1:3] is a copy, whereas c = ylist_view(a,1,3) references the original array. Does it make sense to use this approach in a real Python project or there is some built-in in Python to do that?

\$\endgroup\$
4
\$\begingroup\$

If you are dealing with number lists, then array.array has a compact memory representation and implements the buffer protocol which allows memoryview’s to be created, which directly support views like you are creating.

For lists which can hold other things (tuples, dictionaries, lambdas, ...), Python has no built in support, and your view class can be appropriate.


PEP8 guidelines

Your class name should begin with a capital letter. I’d suggest ListView as an option. I don’t know what the ‘y’ is intended to mean.

There should be one space after every comma. There shouldn’t be any spaces between a variable name and the [ character (b = a[1:3]).

Private members (self.begin, etc) should begin with an underscore (self._begin, etc).

Use a pylint, pyflakes, ... to ensure PEP8 compliance.


You could implement __repr__ in terms of __str__:

    def __repr__(self):
        return str(self)

Extension: Your list view could support a view slice with a step size other than 1.


You don’t protect against indexing beyond the length of your view. i >= self.len.

\$\endgroup\$
  • \$\begingroup\$ thanks got guidelines, its just a dummy example. but are you sure its good to use camel notation in python? 'y' just stand for m'y' i mark own utils with that. You could implement repr in terms of str: -< YES Extension: Your list view could support a view slice with a step size other than 1. <- YES, also 2d view may be possible You don’t protect against indexing beyond the length of your view <- i would say it should be allowed, i dont want extra check and then python list make anotehr check. also \$\endgroup\$ – user8426627 Jul 21 at 17:24
  • \$\begingroup\$ CapWord is good for type names; snake_case is preferred for methods & variable names. Accessing the 10th element of a view of length 5 is a logical error, even if the backing list contains that element. \$\endgroup\$ – AJNeufeld Jul 21 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.