Use magic methods __setitem__() and __getitem__() in Python#
In Python, there are two magic methods that can be used to implement the behavior of the subscript operator []
. These methods are object.__setitem__()
and object.__getitem__()
. The first one is used to assign a value to an item, the second one is used to retrieve an item.
The following example shows how to use these methods to implement a memory class as a list of bytes that was used in the 6502 emulator. The memory class has two methods get()
and set()
that are used to retrieve and assign a value to a memory address.
#!/usr/bin/env python3
class Memory:
def __init__(self, size: int = 65536) -> None:
self.size = size
self.memory = [0] * self.size
for i in range(self.size):
self.memory[i] = 0x00
def get(self, address: int) -> int:
return self.memory[address]
def set(self, address: int, value: int) -> int:
self.memory[address] = value
return self.memory[address]
def main():
memory = Memory()
memory.set(1, 2)
print(memory.get(1))
if __name__ == "__main__":
main()
The same functionality can be implemented using magic methods object.__setitem__()
and object.__getitem__`()
. The advantage of using magic methods is that the memory class can be used as a list of bytes. The following example shows how to use the memory class as a list of bytes. The memory class can be used as a list of bytes because it implements the magic methods object.__setitem__()
and object.__getitem__()
.
#!/usr/bin/env python3
class Memory:
def __init__(self, size: int = 65536) -> None:
self.size = size
self.memory = [0] * self.size
for i in range(self.size):
self.memory[i] = 0x00
def __getitem__(self, address: int) -> int:
return self.memory[address]
def __setitem__(self, address: int, value: int) -> int:
self.memory[address] = value
return self.memory[address]
def main():
memory = Memory()
memory[1] = 2
print(memory[1])
if __name__ == "__main__":
main()
The changes in second example show that interacting with the class becomes more natural. The memory class can be used as a list of bytes because it implements the magic methods object.__setitem__()
and object.__getitem__()
. This way the memory class can be used as a list of bytes by hiding all the implementation details.