[Python-ideas] some useful descriptors + a classtools module (was: Properties for classes possible?)

Eric Snow ericsnowcurrently at gmail.com
Sat Aug 29 23:35:06 CEST 2015


On Sat, Aug 29, 2015 at 3:21 PM, Eric Snow <ericsnowcurrently at gmail.com> wrote:
> I advocate for #3 over the others.  It provides for broader
> application while not impacting the optimizations in classmethod (and
> it has a more accurate name).  It would work similarly to the naive
> classmethod implementation (and work as a less efficient replacement
> for classmethod):
>
> class classresolved:
>     def __init__(self, wrapped):
>         self.wrapped = wrapped
>     def __get__(self, obj, cls):
>         try:
>             getter = self.wrapped.__get__
>         except AttributeError:
>             return self.wrapped
>         return getter(cls, type(cls))
>
> Note that wrapped data descriptors (like property) would behave as
> non-data descriptors since classresolved is itself a non-data
> descriptor.  The case for making it a data descriptor can be treated
> separately, but I don't think that case is as strong.
>
> All this leads to some broader observations about useful, generic
> descriptors in the stdlib.  I'll open a new thread for that
> conversation.

[Just to be clear, I don't have much time to pursue this so it's more
food-for-though than anything.  Feel free to pick up the baton.
<wink>]

While we're on the topic, there are other generic descriptors that are
worth considering for inclusion in the stdlib.  I've written more than
my fair share of descriptors in the past, many to meet real needs. [1]
 Along with "classresolved", here are some non-data descriptors that
might be worth adding:

* lazy - late bound attr that replaces itself on the class (or instance)
* Attr - marks an attr as defined on instances of the class, e.g. to
satisfy an ABC or as programmatic "documentation"; like binding a
place-holder class attr but supports doc strings
* rawattr - basically a synonym for staticmethod
* classattr - equivalent to simply binding the wrapped object directly
on the class, except that wrapped descriptors always resolve as though
called on the class
* classonly - like classattr, but lookup for instances results in
AttributeError; this is like adding a method to a metaclass without
using a metaclass
* nondata - turns data descriptors into non-data descriptors
* classunresolved - causes descriptors to resolve only against
instances; like the inverse of a classonly/classattr combo

[note that I already proposed "classonly" to this list a couple years ago [2]]

While the implementation of many of these is relatively trivial,
understanding of the descriptor protocol (and the attribute lookup
machinery) is just outside the understanding of your average Python
user.  I'm all for changing that but in the meantime I think it's
justifiable to provide useful (even if relatively trivial) descriptors
in the stdlib.  Keep in mind that the implementation of property,
classmethod, and staticmethod have about the same level of complexity
as the descriptors I've described above.

Also, if it makes sense to add any of these (or other) useful
descriptors then it might also make sense for them to live in a stdlib
module rather than as builtins (as property/classmethod/staticmethod
do).  There really isn't a good fit for them currently.

Consequently, I would advocate for adding a new "classtools" module,
inspired by the existing functools and itertools modules.  The new
module would also be an appropriate place for more than descriptors,
as there are likely other things that would fit well there.  In fact
there are a few things we've stuck in the stdlib (e.g. in inspect and
types) that would have gone into a classtools module if it had
existed.

-eric


[1] https://bitbucket.org/ericsnowcurrently/presentations/src/default/utpy-may2015/
[2] https://mail.python.org/pipermail/python-ideas/2013-March/019848.html


More information about the Python-ideas mailing list