Python. Перевантаження операторів. Доступ до елементів за індексом

Перевантаження операторів. Доступ до елементів за індексом. Методи __getitem__() та __setitem__()


Зміст


1. Перевантаження доступу за індексом []. Метод __getitem__()

Щоб забезпечити доступ за індексом в класі, потрібно реалізувати методи __getitem__() та setitem(). Як правило, доступ за індексом потрібен в класах що реалізують набори даних (масиви, списки тощо).

Метод __getitem__() викликається коли потрібно зчитати дані за індексом. Приблизний вигляд оголошення методу в класі може бути таким

class ClassName:
    # Складові класу
    ...

    def __getitem__(self, index):
        ...
        return self.objName[index]

тут

  • ClassName – ім’я класу;
  • objName – ітерований об’єкт, що є списком, кортежем тощо.
  • index – позиція (індекс) елементу в об’єкті objName.

Можна, звичайно, реалізувати метод __getitem__() і не для ітерованого об’єкту вкладаючи в нього певний сенс.

Після оголошення методу __getitem()__ можна звертатись до об’єкту класу у звичний спосіб з допомогою квадратних дужок [ ]

value = ClassName[index] # викликається метод __getitem__()

тут

  • value – деяке значення;
  • index – позиція (індекс) ітерованого об’єкту в класі ClassName.

 

2. Перевантаження доступу за індексом [ ]. Встановлення нового значення. Метод __setitem__()

Метод __setitem()__ викликається, коли потрібно записати дані за індексом в об’єкт класу. Цей об’єкт класу є, як правило, списком, кортежем тощо. Використання методу __setitem__() в класі може бути приблизно таким

class ClassName:
    # Складові класу
    ...

    def __setitem__(self, index, newValue):
        self.objName[index] = newValue

тут

  • ClassName – ім’я класу;
  • objName – ім’я ітерованого об’єкту для якого встановлюється значення newValue в позиції index;
  • index – позиція (індекс) яка починається з 0;
  • newValue – нове значення, яке встановлюється в об’єкті objName.

Після реалізації методу __setitem__() у класі можна буде записувати дані в ітерований об’єкт класу. Це виглядає приблизно так

ClassName[index] = newValue

тут

  • ClassName – ім’я класу що містить ітерований об’єкт;
  • index – позиція елементу в ітерованому об’єкті;
  • newValue – нове значення.

 

3. Приклад, що демонструє реалізацію масиву комплексних чисел та доступ за індексом до елементів масиву

У прикладі оголошується клас ArrayComplex, який містить наступні складові:

  • AC – ім’я масиву комплексних чисел. Масив організований у вигляді списку. Кожен елемент масиву представляє пару (re, im), яка є кортежем;
  • __init__() – конструктор. Створює пустий список AC;
  • метод Add() – забезпечує додавання нового комплексного числа в масив. Число додається як кортеж виду (re, im), який складається з дійсної частини комплексного числа (re) та уявної частини комплексного числа (im);
  • метод Count() – повертає довжину списку AC;
  • метод Print() – виводить список комплексних чисел у зручному вигляді;
  • метод __getitem__() – забезпечує читання за індексом елементу списку AC;
  • метод __setitem__() – забезпечує запис у список чисел AC заданого значення у заданій позиції (індексі).

 

# Доступ за індексом. Перевантаження методів __getitem__(), __setitem__()
# Клас, що реалізує масив комплексних чисел
class ArrayComplex:
    # 1. Конструктор класу
    def __init__(self):
        # масив реалізований у вигляді списку з іменем AC
        self.AC = [] # створити пустий список
        return

    # 2. Метод, що додає комплексне число до списку.
    # Число додається у вигляді кортежу.
    # Тут re - дійсна частина комплексного числа,
    # im - уявна частина комплексного числа.
    def Add(self, re, im):
        self.AC = self.AC + [(re, im)]

    # 3. Метод, що повертає кількість елементів масиву
    def Count(self):
        return len(self.AC) 

    # 4. Метод, що виводить список комплексних чисел на екран
    def Print(self, msg): 
        s = msg + " => [ "
        for c in self.AC:
            s = s + "(" + str(c[0]) + ", " + str(c[1]) + ") "
        s = s + "]"
        print(s)

    # 5. Методи, що забезпечують доступ за індексом []
    # 5.1. Читання елементу масиву за індексом
    def __getitem__(self, index):
        return self.AC[index]

    # 5.2. Запис елементу за індексом,
    #      значення value - це кортеж типу (re, im)
    def __setitem__(self, index, value):
        self.AC[index] = value

# ------- Використання класу -------
# 1. Створити об'єкт класу ArrayComplex
AC = ArrayComplex()

# 2. Додати декілька чисел
AC.Add(5, 8)
AC.Add(2, -4)
AC.Add(-3.5, -1.8)
AC.Add(2.8, 1)

# 3. Вивести вміст об'єкту AC
AC.Print("AC")

# 4. Зчитати перший елемент масиву
cm1 = AC[0] # викликається AC.__getitem__(0)
print("cm1 = ", cm1)

# Зчитати останній елемент масиву
cm2 = AC[AC.Count()-1]
print("cm2 = ", cm2)

# 5. Записати нове значення у масив в позиції 1
AC[1] = (10, 20) # викликається AC.__setitem__(1, (10, 20))

# 6. Повторно вивести масив
AC.Print("AC")

# 7. Отримати об'єкт зрізу та вивести зріз
objSlice = AC[:AC.Count()]
print("Slice[:Count()-1] => ", objSlice)

# 8. Отримати зріз, який містить перші 2 елементи
objSlice = AC[:3]
print("Slice[:2] => ", objSlice)

Результат

AC => [ (5, 8) (2, -4) (-3.5, -1.8) (2.8, 1) ]
('cm1 = ', (5, 8))
('cm2 = ', (2.8, 1))
AC => [ (5, 8) (10, 20) (-3.5, -1.8) (2.8, 1) ]
('Slice[:Count()-1] => ', [(5, 8), (10, 20), (-3.5, -1.8), (2.8, 1)])
('Slice[:2] => ', [(5, 8), (10, 20), (-3.5, -1.8)])

 

4. Приклад, що демонструє доступ до об’єкту класу за індексом. Реалізація класів Point та ListPoints

 

# Доступ за індексом
# Клас, що описує точку на координатній площині,
# у класі використовуються внутрішні поля x, y
class Point:
    # 1. Конструктор класу
    def __init__(self, x, y):
        self.x = x
        self.y = y
        return

    # 2. Методи доступу
    # 2.1. Встановити нове значення x
    def SetXY(self, x, y):
        self.x = x
        self.y = y
        return

    # 2.2. Зчитати x, y
    def X(self) : return self.x
    def Y(self) : return self.y

    # Метод, що виводить точку на екран
    def Print(self, msg):
        s = msg + " = (" + str(self.x) + "; " + str(self.y) + ")";
        print(s)

# Клас, що описує масив точок, який має ім'я AP
class ListPoints:
    # конструктор
    def __init__(self):
        self.AP = [] # Створити пустий список

    # Метод, що додає точку в кінець списку
    def Add(self, pt):
        self.AP = self.AP + [pt]

    # Метод, що повертає список точок
    def GetList(self): return self.AP

    # Метод, що виводить список точок
    def Print(self, msg):
        s = msg + " = [" # сформувати рядок виведення
        for p in self.AP:
            s = s + "(" + str(p.X()) + "; " + str(p.Y()) + ") "
        print(s + ']\n')

    # Методи, що реалізують доступ за індексом
    # Отримати точку з індексом index
    def __getitem__(self, index):
        return self.AP[index]

    # Записати нову точку в позиції index
    def __setitem__(self, index, value):
        self.AP[index] = value

# ------- Використання класів Point та ListPoints -------
# 1. Створити деяку точку
p1 = Point(2, 8.3)
p1.Print("p1")

# 2. Створити масив точок типу Point
# 2.1. Створити пустий масив
ArrayPoints = ListPoints()

# 2.2. Додати до масиву 3 точки
ArrayPoints.Add(p1) # Додати точку p1
ArrayPoints.Add(Point(3, 7.1)) # додати точку (3, 7.1)
ArrayPoints.Add(Point(2, 1.6))

# 2.3. Вивести масив точок
ArrayPoints.Print("ArrayPoints")

# 3. Зчитати точку з індексом 0
pt = ArrayPoints[0] # тут викликається метод __getitem__()
pt.Print("ArrayPoints[0]") #

# 4. Записати нове значення в точку з індексом 1
ArrayPoints[1] = Point(1.5, 2.3) # викликаєтсья метод __setitem__()

# 5. Вивести масив заново
ArrayPoints.Print("ArrayPoints")

Результат

p1 = (2; 8.3)
ArrayPoints = [(2; 8.3) (3; 7.1) (2; 1.6) ]

ArrayPoints[0] = (2; 8.3)
ArrayPoints = [(2; 8.3) (1.5; 2.3) (2; 1.6) ]

 


Споріднені теми