Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override __getitem__ when it's a class method?

class Custom(type):
    @classmethod
    def __getitem__(cls, item):
        raise NotImplementedError("")

    @classmethod
    def test(cls):
        print("class custom : test")

class Book(metaclass=Custom):
    Note = 0
    Pad = 1

    Name = { Note : "Note", Pad : "Pad"}

    @classmethod
    def __getitem__(cls, item):
        return Book.Name[item]

    @classmethod
    def test(cls):
        print("class book: test")

My intention is to have

Book[Book.Note] returns "Note"

It seems __getitem__() is not overrideable, unlike test(). How do I make it work ?

like image 809
user1502776 Avatar asked May 31 '15 03:05

user1502776


1 Answers

You're using a metaclass here. This isn't strictly inheritance: you've defined the class of the class Book as Custom, whereas it used to be type. Because magic methods like __getitem__ are looked up directly on the class, and not on the instance, indexing Book[whatever] will actually call the __getitem__ method of the class of Book, which happens to be Custom.

My intention is to have

Book[Book.Note] 

returns "Note"

In that case, you should make the class of Book implement __getitem__ such that it returns "Note". Since the class of Book is Custom, this is where the change needs to be made:

class Custom(type):
    def __getitem__(cls, item):
        return cls.Name[item]
    ...

class Book(metaclass=Custom):
    ... # as is, although you don't need the @classmethod __getitem__

Book[Book.Note] # "Note"
Book[1]         # "Pad"
like image 76
Asad Saeeduddin Avatar answered Sep 18 '22 02:09

Asad Saeeduddin