Python Forum
Emulate slicing for a method
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Emulate slicing for a method
#1
Hi,

Is there a way to make a method sliceable? For example:
my_instance.look_up[3:6]
Pandas has the DataFrame class. It needs to make a new copy if you add data, perhaps because it uses an ndarray internally? I don't know. But I want to add data continuously and not have the copies so I'm trying to create a class similar to pandas.DataFrame using dict+lists. DataFrame has a method DataFrame.loc that accepts slice notation which I would like to have too.

Here's what I've got:
#!/usr/bin/env python3

class DataFrame:
    def __init__(self, max_frame_length):
        self.max_frame_length = max_frame_length
        self.data = {}

    def __getitem__(self, key):
        print('__getitem__', key)

    def add_data(self, label, value):
        if not label in self.data:
            self.data[label] = [value]
        else:
            self.data[label].append(value)

    def loc(self, key):
        print('loc', key)


fname = 'smallset.txt'
def read_line(fname):
    with open(fname) as f:
        for i, line in enumerate(f):
            a, b, c = line.split(';')
            data = [float(item) for item in [a, b, c]]
            yield i, data


foo = DataFrame(200)
for i, data in read_line(fname):
    a, b, c = stick
    foo.add_data('index', i)
    foo.add_data('a', a)
    foo.add_data('b', b)
    foo.add_data('c', c)

# This works
foo[1:2]
# This doesn't
foo.loc[1:2]
I think I need to use __getitem__ somehow but I don't know how to pass the slice to the method. Any ideas?

Thanks in advance.
Reply
#2
I don't think loc is a method, I think it's an attribute. Python is going to call __getitem__ for the attribute, not the class. So you want an attribute that is aware of the object it is an attribute of, and you want to override that attribute's __getitem__. That is, that attribute will have to be a separate class in and of itself.

But __getitem__ has nothing to do with adding data. For that you need to mess override __setitem__.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
This works:
class Loc:
    def __getitem__(self, key):
        print(key.start, key.stop, key.step)

class DataFrame:
    def __init__(self, max_frame_length)
        self.max_frame_length = max_frame_length
        self.data = {}
        self.loc = Loc()
Thanks Ichabod!
Reply
#4
Properties are usually decorated methods - so loc is not an attribute

Output:
In [7]: pandas.DataFrame.loc Out[7]: <property at 0x7fd722e2ce58> In [9]: pandas.DataFrame.loc?? Type: property String form: <property object at 0x7fd722e2ce58> Source: # pandas.DataFrame.loc.fget pandas.DataFrame.loc.fget = functools.partial(<class 'pandas.core.indexing._LocIndexer'>, 'loc')
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#5
Properties are descriptors. Descriptors are attributes. (https://docs.python.org/3/howto/descriptor.html)
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#6
It looks like pandas indeed does use classes for this as seen here. It also looks like a complex project!
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020