Переопределение __getitem__

#python-3.x #metaclass

#python-3.x #метакласс

Вопрос:

Я создаю класс и хочу, чтобы следующий синтаксис «numpy like» работал:

 #simple example
class MyClass():
    def __init__(self):
        self.arr = [1,2,3,4]

    def __getitem__(self, index):
        return self.arr[index]
    
    def print_next(self,index):
        print(self.arr(index 1))

    def print_previous(self,index):
        print(self.arr(index-1))

a = MyClass()
a.arr[2].print_next() #4
a.arr[2].print_previous() #2
  

__getitem__ позволяет мне получить доступ только к индексу, а не к последующему вызову метода. Я изучаю метаклассы для изменения __getitem__ , но я не могу понять, как поступить.

Комментарии:

1. Можете ли вы привести пример того, что вы пытаетесь сделать в numpy?

2. Ну, вызов метода, который следует после, является методом для класса MyClass . Если ваша цель состоит в том, чтобы затем вызвать метод, подобный hat, __getitem__ нужно было бы вернуть self .

3. Привет! Добро пожаловать в SO! Пожалуйста, не забудьте добавить как можно больше информации к вашему вопросу, предоставленный вами код не будет выполняться из-за ошибок типа, которые не описаны как часть вашего вопроса. Кроме того, было бы неплохо объяснить, чего вы пытаетесь достичь, и, если возможно, показать пример (возможно, используя NumPy в качестве ссылки?). Заранее спасибо!

Ответ №1:

Вы можете сделать что-то вроде этого:

 In [86]: class MyClass():
    ...:     def __init__(self):
    ...:         self.arr = [1,2,3,4]
    ...:         self.index = None
    ...:
    ...:     def __getitem__(self, index):
    ...:         self.index = index
    ...:         return self
    ...:
    ...:     def print_next(self):
    ...:         print(self.arr[self.index 1])
    ...:
    ...:     def print_previous(self):
    ...:         print(self.arr[self.index-1])
    ...:
  

На самом деле вам не нужен другой аргумент для print_next или print_previous , поскольку вы надеетесь снова вызвать метод.

Хотя это не рекомендуется, так как вы переопределяете, __getitem__ чтобы просто вернуть self и установить переменную.

Но теперь вы можете сделать это:

 In [90]: a[2].print_next()
4
In [91]: a[2].print_previous()
2
  

Комментарии:

1. Спасибо, это было проще, чем я думал, но я не мог этого придумать. Вы отлично ответили на мой вопрос!

2. Нет проблем. Возможно, вы также захотите выполнить некоторые проверки работоспособности внутри него. Например, инициализируйте self.index = 0 и убедитесь, что следующий и предыдущий элементы находятся в пределах допустимых индексов.