-1

When I was working with Colorgram Library, I came across a [:] operator that I didn't understand.

print(extraction[0]) prints [<colorgram.py Color: Rgb(r=245, g=243, b=238), 64.68350168350169%> Then extraction[0].rgb prints Rgb(r=245, g=243, b=238).

Here is the most confusing part:

When I enter print(extraction[0].rgb[:]), it prints (245, 243, 238). How exactly does the [:] operator work here?

import colorgram
 
extraction = colorgram.extract('img.jpg', 30)
colors = []
 
for c in extraction:
    colors.append(c.rgb[:])
 
print(colors)
opeonikute
  • 494
  • 1
  • 4
  • 15

2 Answers2

0

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)
0

According to the PyPi Colorgram Docs:

colorgram.Color A color extracted from an image. Its properties are:

Color.rgb - The color represented as a namedtuple of RGB from 0 to 255, e.g. (r=255, g=151, b=210).

What is a Named Tuple?

  1. A named tuple is a subclass of a regular tuple provided by the collections module. It allows you to define a new tuple type with named fields (like attributes of an object) along with their corresponding indices.
  2. Named tuples are also immutable, just like regular tuples.
  3. Named tuples offer the advantage of more readable and self-documenting code since you can access fields by their names instead of integer indices.
  4. Named tuples have built-in methods for conversion to dictionary and string representation, which can be useful.

In your example, the Color named tuple is defined like so:

>>> from collections import namedtuple  
>>> Color = namedtuple('Rgb', ['r', 'g', 'b'])
>>> my_color = Color(245, 243, 238)

If you try printing my_color:

>>> my_color
Rgb(r=245, g=243, b=238)
>>> type(my_color)
<class '__main__.Rgb'>

Now, if you try printing mycolor[:], you will notice the type of the sliced named tuple is no longer of type Rgb, but rather a vanilla Python tuple.

>>> print(my_color[:])
(245, 243, 238)
>>> type(my_color[:])
<class 'tuple'>

If colorgram provides you with a named tuple, you can of course use indexing like with any tuple, but you can also access the attributes by name. For example, if I would like to access the g parameter of the Rgb tuple I can do any of the following.

>>> my_color[1]
243
>>> my_color.g
243
>>> getattr(my_color, 'g')
SaptakD625
  • 89
  • 4