Suppose following class:
class Class(object):
@classmethod
def getitem(*args):
print 'getitem %s' % (args,)
@classmethod
def __getitem__(*args):
print '__getitem__ %s' % (args,)
The getitem method behaves as expected: it receives Class as first arg, but __getitem__ receives type as first arg:
calling Class.getitem(test)
getitem (<class '__main__.Class'>, 'test')
calling obj.getitem(test)
getitem (<class '__main__.Class'>, 'test')
calling Class[test]
'type' object has no attribute '__getitem__'
calling obj[test]
__getitem__ (<class '__main__.Class'>, 'test')
What is the magic there behind __getitem__ ?
Special methods are looked up on the class, and not on the instance – unlike regular methods that are looked up on the instance first. See Special method lookup in the Python data model docs.
Thinking about
Classas an instance oftype, this means when you doIt looks first for exactly what you tell it: a method in
Class‘s own attributes calledgetitem. But, when you useit skips this, and goes straight to
type(being the class ofClass, or its metaclass), and so callstype.__getitem__(Class, test). So, what’s happening isn’t that__getitem__getstypeas its first argument (it would still getClass, as it does if you explicitlyClass.__getitem__(test)), its that the__getitem__that Python looks for in this case doesn’t exist. To make it exist, you need to define your own metaclass forClassthat defines it as an instance method, rather than defining it onClassas a classmethod.