[Python-Dev] Getting rid of unbound methods: patch available (original) (raw)
M.-A. Lemburg mal at egenix.com
Wed Jan 19 12:27:29 CET 2005
- Previous message: [Python-Dev] Getting rid of unbound methods: patch available
- Next message: [Python-Dev] Getting rid of unbound methods: patch available
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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 imclass? [Marc-Andre] It uses imclass 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,useclipboard=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 .imclass 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 imself 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 PyMethodCheck() 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
* 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 imclass 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 ! ::::
- Previous message: [Python-Dev] Getting rid of unbound methods: patch available
- Next message: [Python-Dev] Getting rid of unbound methods: patch available
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]