getting special from type, not instance (was Re: [Python-Dev] copy confusion)

Guido van Rossum gvanrossum at gmail.com
Wed Jan 12 18:59:13 CET 2005


[Alex]
> Armin's fix was to change:
> 
>     conform = getattr(type(obj), '__conform__', None)
> 
> into:
> 
>     for basecls in type(obj).__mro__:
>         if '__conform__' in basecls.__dict__:
>             conform = basecls.__dict__['__conform__']
>             break
>     else:
>         # not found
> 
> I have only cursorily examined the rest of the standard library, but it
> seems to me there may be a few other places where getattr is being used
> on a type for this purpose, such as pprint.py which has a couple of
> occurrences of
>      r = getattr(typ, "__repr__", None)
[And then proceeds to propose a new API to improve the situation]

I wonder if the following solution wouldn't be more useful (since less
code will have to be changed).

The descriptor for __getattr__ and other special attributes could
claim to be a "data descriptor" which means that it gets first pick
*even if there's also a matching entry in the instance __dict__*.
Quick illustrative example:

>>> class C(object):
     foo = property(lambda self: 42)   # a property is always a "data
descriptor"
    
>>> a = C()
>>> a.foo
42
>>> a.__dict__["foo"] = "hello"
>>> a.foo
42
>>> 

Normal methods are not data descriptors, so they can be overridden by
something in __dict__; but it makes some sense that for methods
implementing special operations like __getitem__ or __copy__, where
the instance __dict__ is already skipped when the operation is invoked
using its special syntax, it should also be skipped by explicit
attribute access (whether getattr(x, "__getitem__") or x.__getitem__
-- these are entirely equivalent).

We would need to introduce a new decorator so that classes overriding
these methods can also make those methods "data descriptors", and so
that users can define their own methods with this special behavior
(this would be needed for __copy__, probably).

I don't think this will cause any backwards compatibility problems --
since putting a __getitem__ in an instance __dict__ doesn't override
the x[y] syntax, it's unlikely that anybody would be using this.
"Ordinary" methods will still be overridable.

PS. The term "data descriptor" now feels odd, perhaps we can say "hard
descriptors" instead. Hard descriptors have a __set__ method in
addition to a __get__ method (though the __set__ method may always
raise an exception, to implement a read-only attribute).

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list