@StaticMethod or @ClassMethod decoration on magic methods
Question: I am trying to decorate the magic method `__getitem__` to be a classmethod on
the class. Here is a sample of what I tried. I don't mind using either
classmethod or staticmethod decoration, but I am not too sure how to do it.
Here is what I tried:

    
    
    import ConfigParser
    
    class Settings(object):
       _env = None
       _config = None
    
       def __init__(self, env='dev'):
        _env = env
        # find the file
        filePath = "C:\\temp\\app.config"
    
        #load the file
        _config = ConfigParser.ConfigParser()
        _config.read(filePath)
    
       @classmethod
       def __getitem__(cls, key): 
        return cls._config.get(cls._env, key)
    
       @classmethod
       def loadEnv(cls, env): 
        cls._env = env
    

However, when I try to call `Settings['database']` I get the following error.

    
    
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: expected Array[Type], got str
    

Can anyone tell me what I am doing wrong. Also, could someone suggest if there
is better way to do this? I even tried using MetaClasses, but with little
success (as I don't know python too well).

    
    
     class Meta(type):
      def __getitem__(*args):
       return type.__getitem__(*args)
    
     class Settings(object):
      __metaclass__ = Meta
    

Thanks in advance.


Answer: Python always looks up `__getitem__` and other magic methods on the class, not
on the instance. So, for example, defining a `__getitem__` in a metaclass
means that you can index **the class** (but you can't define it by delegating
to a non-existent `__getitem__` in `type` \-- just as you can never define
anything by delegating to other non-existent methods, of course;-).

So, if you need to index a class such as `Settings`, your custom metaclass
must indeed define `__getitem__`, but it must define it with explicit code
that performs the action you desire -- the `return cls._config.get` you want.

**Edit** : let me give a simplified example...:

    
    
    >>> class MyMeta(type):
    ...   def __getitem__(cls, k):
    ...     return cls._config.get(k)
    ... 
    >>> class Settings:
    ...   __metaclass__ = MyMeta
    ...   _config = dict(foo=23, bar=45)
    ... 
    >>> print Settings['foo']
    23
    

Of course, if that was all there was to it, it would be silly to architect
this code as "indexing a class" -- a class had better have instances with
states and methods, too, otherwise you should just code a module instead;-).
And why the "proper" access should be by indexing the whole class rather than
a specific instance, etc, is far from clear. But I'll pay you the compliment
of assuming you have a good design reason for wanting to structure things this
way, and just show you _how_ to implement such a structure;-).

