2.2 descriptor API

Daniel Popowich sfconsulting at attbi.com
Mon Apr 8 11:51:48 EDT 2002


Guido van Rossum <guido at python.org> wrote in message news:<3CADF520.C0264C0B at python.org>...
> Daniel Popowich wrote:
> > 1.  Why is the __get__ method called on a descriptor when it is
> >     referenced as a class attribute?
> 
> This was a requirement.  When you get a method out of a class in Python 2.1
> and before, it gets special treatment which gives you an "unbound method".
> The unbound method insists that you call it with an instance of the right
> class, in order to prevent mistakes.  The new descriptor API must be able
> to support similar behavior.  But it must also support other behavior, like
> class methods and static methods.
> 
> > 2.  What is the purpose behind the second argument; does someone have
> >     an example of how or when I would make use of it?
> 
> When __get__ is called on a class, the first argument is None, and the
> second argument is the class.
> 
> --Guido van Rossum (home page: http://www.python.org/~guido/)



My questions had more to do with design than technical facts.  It
strikes me that the __get__ method is not so much the publication of a
new API, but rather the exposure of low-level, run-time interpreter
mechanics.  Essentially, you've exposed the necessary arguments so one
can call PyMethod_New (via the new module's instancemethod) to bind a
function to a class:

    class myclassmethod(object):
	def __init__(self, func):
	    self.func = func

	def __get__(self, obj, type=None):
	    return new.instancemethod(self.func, type, type.__class__)

But I question the utility of this for Joe Schmoe, python programmer.
If instead of using the descriptor api, the language had constructs
like the following to define methods:

    class Foo:
       # static method definition
       def static foo(*args): pass

       # class method definition
       def class bar(cls, *args): pass

       # instance method definition
       def baz(self, *args): pass

in other words, after "def", allow a qualifier (or perhaps a list of
qualifiers) before the function name, then the interpreter can mark
the functions appropriately and do the right magic when the
class/instance attribute is accessed (*).

I understand that a method like the current __get__ is necessary at
SOME level of the interpreter, I just question the utility of exposing
it.  What I would prefer seeing for __get__ is symmetry with __set__
and __delete__, that is, its signature being: __get__(self, obj) and
it is only called on references to bound instances.  

As for referencing class attributes: I think the interpreter should
always return the value of the attribute, doing magic on methods to
return the proper binding based on its definition.  For the
power-programmer (that rare individual who needs to program their own
version of staticmethod or classmethod) there's always the new module.

Thanks for listening,

Daniel Popowich


(*) this would also remove another blemish from the language: having
to define a function and LATER redefine to make it a static or class
method.  It's far from intuitive, not very readable (especially in the
case of lengthy methods) and, I imagine, difficult for introspection
tools (eg, doc generators) to recognize them.  In short, using the
descriptor API to create static/class methods is un-pythonic, a wart.



More information about the Python-list mailing list