__getitem__ method on (meta)classes
Bengt Richter
bokr at oz.net
Mon Mar 14 21:48:58 EST 2005
On 14 Mar 2005 17:43:53 -0800, ron at flownet.com wrote:
>
>Why doesn't this work?
>
>>>> def foo(lst):
>... class baz(object):
>... def __getitem__(cls, idx): return cls.lst[idx]
>... __getitem__=classmethod(__getitem__)
>... baz.lst = lst
>... return baz
>...
>>>> f = foo([1,2,3])
>>>> f[0]
>Traceback (most recent call last):
> File "<stdin>", line 1, in ?
>TypeError: unsubscriptable object
>>>> f.__getitem__(0)
>1
>>>>
>
>
>I thought x[y] and x.__getitem__(y) were supposed to always be
>synonymous.
Yes, but what was your "x"?
Note:
>>> def foo(lst):
... class baz(object):
... def __getitem__(cls, idx): return cls.lst[idx]
... __getitem__ = classmethod(__getitem__)
... baz.lst = lst
... return baz
...
>>> f = foo([1,2,3])
>>> f
<class '__main__.baz'>
Your "x" was the baz *class*, and the baz *class* is not subscriptable *itself*,
even though it defines subscripting for its instances.
To be ordinarily subscriptable, type(f).__getitem__ would have to succeed, which it doesn't:
>>> type(f)
<type 'type'>
>>> type(f).__getitem__
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: type object 'type' has no attribute '__getitem__'
However, a baz instance is different:
>>> finst = f()
>>> finst
<__main__.baz object at 0x02EF168C>
Its type does have a __getitem__ attribute:
>>> type(finst).__getitem__
<bound method type.__getitem__ of <class '__main__.baz'>>
I think "bound method" is a bit of a misnomer for a classmethod, though
it is a method, and it is bound, just to the class instead of the instance.
(see below)
>>> type(finst).__getitem__(0)
1
Or straightforward indexing syntax:
>>> finst[0], finst[1], finst[2]
(1, 2, 3)
Contrast with the way an ordinary method repr's when you access it
via class and instance:
>>> class C(object):
... def ordinary_method(self): return 'Hi'
...
>>> c=C()
>>> C.ordinary_method
<unbound method C.ordinary_method>
>>> c.ordinary_method
<bound method C.ordinary_method of <__main__.C object at 0x02EF164C>>
>>> c.ordinary_method()
'Hi'
>>> C.ordinary_method
<unbound method C.ordinary_method>
>>> C.ordinary_method(c)
'Hi'
Note the difference between ordinary and classmethod:
>>> type(c).ordinary_method
<unbound method C.ordinary_method>
>>> type(finst).__getitem__
<bound method type.__getitem__ of <class '__main__.baz'>>
BTW, I see a class factory, but no "(meta)"class per se.
Regards,
Bengt Richter
More information about the Python-list
mailing list