Guido van Rossum wrote:
[me]
I'm not sure I understand how basemethod is supposed to work; I can't
find docs for it using Google (only three hits for the query mxTools
basemethod). How does it depend on im_class?
[Marc-Andre]
It uses im_class to find the class defining the (unbound) method:
def basemethod(object,method=None):
""" Return the unbound method that is defined *after* method in the
inheritance order of object with the same name as method
(usually called base method or overridden method).
object can be an instance, class or bound method. method, if
given, may be a bound or unbound method. If it is not given,
object must be bound method.
Note: Unbound methods must be called with an instance as first
argument.
The function uses a cache to speed up processing. Changes done
to the class structure after the first hit will not be noticed
by the function.
"""
...
This is how it is used in mixin classes to call the base
method of the overridden method in the inheritance tree (of
old-style classes):
class RequestListboxMixin:
def __init__(self,name,viewname,viewdb,context=None,use_clipboard=0,
size=None,width=None,monospaced=1,events=None):
# Call base method
mx.Tools.basemethod(self, RequestListboxMixin.__init__)\
(self,name,size,width,monospaced,None,events)
...
Without .im_class for the unbound method, basemethod would
seize to work since it uses this attribute to figure out
the class object defining the overriding method.
Well, you could always do what Timothy Delaney's autosuper recipe
does: crawl the class structure starting from object.__class__ until
you find the requested method. Since you're using a cache the extra
cost should be minimal.
That won't work, since basemethod() is intended for standard
classes (not new-style ones).
I realize that this requires you to issue a new release of mxTools to
support this, but you probably want to do one anyway to support other
2.5 features.
A new release wouldn't be much trouble, but I don't see any
way to fix the basemethod() implementation without also requiring
a change to the function arguments.
Current usage is basemethod(instance, unbound_method). In order
for basemethod to still be able to find the right class and
method name, I'd have to change that to basemethod(instance,
unbound_method_or_function, class_defining_method).
This would require all users of mx.Tools.basemethod() to
update their code base. Users will probably not understand
why this change is necessary, since they'd have to write
the class twice:
mx.Tools.basemethod(self,
RequestListboxMixin.__init__,
RequestListboxMixin)\
(self,name,size,width,monospaced,None,events)
Dropping the unbound method basically loses expressiveness:
without extra help from function attributes or other descriptors,
it would no longer be possible to whether a function is to be
used as method or as function. The defining namespace of the method
would also not be available anymore.
Hmm, I have a hard time seeing how you can get rid
off unbound methods while keeping bound methods - since
both are the same type :-)
Easy. There is a lot of code in the instance method type specifically
to support the case where im_self is NULL. All that code can be
deleted (once built-in exceptions stop using it).
So this is not about removing a type, but about removing
extra code. You'd still keep bound methods as separate
type.
I'm using PyMethod_Check() in mxProxy to automatically
wrap methods of proxied object in order to prevent references
to the object class or the object itself to slip by the
proxy. Changing the type to function object and placing
the class information into a function attribute would break
this approach. Apart from that the type change (by itself)
would not affect the eGenix code base.
Isn't mxProxy a weak referencing scheme? Is it still useful given
Python's own support for weak references?
Sure. First of all, mxProxy is more than just a weak referencing
scheme (in fact, that was only an add-on feature).
mxProxy allows you to wrap any Python object in way that hides
the object from the rest of the Python interpreter, putting
access to the object under fine-grained and strict control.
This is the main application space for mxProxy.
The weak reference feature was added later on, to work around
problems with circular references. Unlike the Python weak
referencing scheme, mxProxy allows creating weak references
to all Python objects (not just the ones that support the
Python weak reference protocol).
I would expect code in the following areas to make use
of the type check:
* language interface code (e.g. Java, .NET bridges)
Java doesn't have the concept of unbound methods, so I doubt it's
useful there. Remember that as far as how you call it, the unbound
method has no advantages over the function!
True, but you know that its a method and not just a function.
That can make a difference in how you implement the call.
* security code that tries to implement object access control
Security code should handle plain functions just as well as (un)bound
methods anyway.
It is very important for security code to know which attributes
are available on an object, e.g. an unbound method includes
the class object, which again has a reference to the module,
the builtins, etc.
Functions currently don't have this problem (but will once you add the
im_class attribute ;-).
* RPC applications that use introspection to generate
interface definitions (e.g. WSDL service definitions)
Why would those care about unbound methods?
I was thinking of iterating over the list of methods in
a class:
To find out which of the entries in the class
dict are methods, a tool would have to check whether
myClass.myMethod maps to an unbound method (e.g.
non-function callables are currently not wrapped as
unbound methods).
Example:
>>> class C:
... def test(self):
... print 'hello'
... test1 = dict
...
>>> C.test1
<type 'dict'>
>>> C.test
<unbound method C.test>
* debugging tools (e.g. IDEs)
Hopefuly those will use the filename + line number information in the
function object. Remember, by the time the function is called, the
(un)bound method object is unavailable.
I was thinking more in terms of being able to tell whether
a function is a method or not. IDEs might want to help
the user by placing a "(self," right after she types the
name of an unbound method.
If you want to make methods look more like functions,
the method object should become a subclass of the function
object (function + added im_* attributes).
Can't do that, since the (un)bound method object supports binding
other callables besides functions.
Is this feature used anywhere ?
Yes, by the built-in exception code. (It surprised me too; I think in
modern days it would have been done using a custom descriptor.)
BTW, decorators and other descriptors are one reason why approaches
that insist on im_class being there will have a diminishing value in
the future.
True, as long as you put the information from im_class somewhere
else (where it's easily accessible). However, I wouldn't want
to start writing
@method
def funcname(self, arg0, arg1):
return 42
just to tell Python that this particular function will only
be used as method ;-)
--
Marc-Andre Lemburg
eGenix.com
Professional Python Services directly from the Source (#1, Jan 10 2005)
>>> Python/Zope Consulting and Support ... http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________
::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,FreeBSD for free ! ::::
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com