
On Sat, Aug 29, 2015 at 3:21 PM, Eric Snow <ericsnowcurrently@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-may20... [2] https://mail.python.org/pipermail/python-ideas/2013-March/019848.html