New-style classes and special methods
Alex Martelli
aleax at aleax.it
Mon Feb 24 04:07:34 EST 2003
Andrew Bennetts wrote:
> On Mon, Feb 24, 2003 at 07:13:44AM +0000, Carl Banks wrote:
>> Jp Calderone wrote:
>> > [-- text/plain, encoding quoted-printable, 37 lines --]
>> >
>> > Consider this class:
>> >
>> > class Foo:
>> > def __getattr__(self, name):
>> > return lambda arg: arg
>> >
>> > It can be used thusly:
>> >
>> > f = Foo()
>> > print f[10]
>>
>> Sure?
>
> >>> class Foo:
> ... def __getattr__(self, name):
> ... return lambda arg: arg
> ...
> >>> f = Foo()
> >>> print f[10]
> 10
>
> Yep, I'd say he's sure.
Indeed. For the benefit of readers who might be puzzled by
this: Python uses __getattr__ to look up (almost) ALL
attributes not found by other means -- including special
methods. Here, when you write f[10], Python looks for special
method __getitem__ -- and since f instances a classic class,
Python looks for said method per-instance, and does so (not
having found it by other means) by calling f.__getattr__ ...
and getting the "lambda arg: arg" callable as the result.
Of course, this class is nearly unusable...:
>>> f
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: <lambda>() takes exactly 1 argument (0 given)
>>> f+2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: coercion should return None or 2-tuple
>>> f == 23
23
>>>
as its instances claim to have all kinds of special methods
which in fact they do not implement with proper signatures
(all "special methods" end up with the one-mandatory-argument
signature of that naughty "lambda arg: arg" trick).
Add something like "print 'returning fake',name" as the
first statement in the body of that __getattr__ to see what
is going on in a bit more detail.
If you want to create a similarly-unusable class of the
new-style persuasion, you can do it with a custom metaclass,
of course. Left as an exercise for the true masochists...;-)
Alex
More information about the Python-list
mailing list