for you to fully grasp this concept you need to understand 2 mechanics of python
operator overloading
and
slicing
first we'll take a look at slicing cause it's much easier than operator overloading
take a look at code below:
my_list = [1, 2, 3, 4, 5]
print(my_list[0])
print(my_list[1:3])
print(my_list[:2])
print(my_list[:])
print(my_list[2:4][::-1])
print(my_list[::-1])
when we slice an list/tuple or any other indexable type we tend to ask for some part of its data with a start and end index
I would explain it as [x, y, z] where x is the start index of the slice y is the ending index and z is either 1 or -1 for direction of the slice
so output of the code above is :
1
[2, 3]
[1, 2]
[1, 2, 3, 4, 5]
[]
[5, 4, 3, 2, 1]
getting the slicing part out the way we need to think about classes and concept of operator overloading
class MyClass:
def __init__(self, red, green, blue):
self.red = red
self.green = green
self.blue = blue
def __str__(self):
return f"Rgb(r={self.red}, g={self.green}, b={self.blue})"
def __getitem__(self, key):
return (self.red, self.green, self.blue)[key]
my_instance = MyClass(100, 152, 180)
print(my_instance)
print(my_instance[:])
in python classes every method that starts with 2 underscores and ends with 2 other are reserved methods called dunder methods (double underscore methods)
when you write "c.rgb" you access some object like MyClass in my example
that when you print it, it class str method and generates a string representation of object
and when you use [] operator (square brackets count as operators like -, +, *, /, %, etc...) it calls the getitem method which is maybe implemented the way I did that causes you to see that output
so the confusion is not about slice operator it's about implementation
of rgb class
output of running my code example no.2:
Rgb(r=100, g=152, b=180)
(100, 152, 180)