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