[Python-ideas] Having unbound methods refer to the classes their defined on

cool-RR cool-rr at cool-rr.com
Wed Jun 2 10:59:45 CEST 2010


On Wed, Jun 2, 2010 at 8:36 AM, Gmail <arnodel at googlemail.com> wrote:

>
> On 1 Jun 2010, at 18:36, cool-RR wrote:
>
> Hello,
>
> I would like to raise an issue here that I've been discussing at
> python-porting.
>
> (And I'd like to preface by saying that I'm not intimately familiar with
> Python's innards, so if I make any mistakes please correct me.)
>
> In Python 2.x there was an "unbound method" type. An unbound method would
> have an attribute `.im_class` that would refer to the class on which the
> method was defined. This allowed users to use the `copy_reg` module to
> pickle unbound methods by name. (In a similar way to how functions and
> classes are pickled by default.)
>
>
> Not exactly (python 2.6):
>
> >>> class Foo(object):
> ...    def f(self): pass
> ...
> >>> Foo.f
> <unbound method Foo.f>
> >>> Foo.f.im_class
> <class '__main__.Foo'>
> >>> class Bar(Foo): pass
> ...
> >>> bar.f
> <unbound method Bar.f>
> >>> Bar.f.im_class
> <class '__main__.Bar'>
>
>
> In Python 3.x unbound methods are plain functions. There is no way of
> knowing on which class they are defined, so therefore it's impossible to
> pickle them. It is even impossible to tell `copyreg` to use a custom
> reducer:
>
> http://stackoverflow.com/questions/2932742/python-using-copyreg-to-define-reducers-for-types-that-already-have-reducers
>
> (To the people who wonder why would anyone want to pickle unbound methods:
> I know that it sounds like a weird thing to do. Keep in mind that sometimes
> your objects need to get pickled. For example if you're using the
> multiprocessing module, and you pass into it an object that somehow refers
> to an unbound method, then that method has to be picklable.)
>
> The idea is: Let's give unbound methods an attribute that will refer to the
> class on which they were defined.
>
> What do you think?
>
>
> Unbound methods in Python 2.X were objects that were created on class
> attribute access, not when the class was created, so what you are asking for
> is different from what Python 2.X provided.  Here is a very simplified way
> to mimic 2.X in 3.X via metaclasses (Python 3.2):
>
> >>> class FooType(type):
> ...     def __getattribute__(self, attrname):
> ...         attr = super().__dict__[attrname]
> ...         if isinstance(attr, type(lambda:0)):
> ...             return ("unbound method", self, attr)
> ...         else:
> ...             return attr
> ...
> >>> class Foo(metaclass=FooType):
> ...     def f(self):pass
> ...
> >>> Foo.f
> ('unbound method', <class '__main__.Foo'>, <function f at 0x445fa8>)
> >>> Foo().f()
> >>>
>
> What you want maybe instead is a metaclass that overrides type.__new__ or
> type.__init__ so that each function in the attributes of the class is
> wrapped in some kind of wrapper like this:
>
> class DefinedIn:
>     def __init__(self, f, classdef):
>         self.classdef = classdef
>         self.f = f
>     def __call__(self, *args, **kwargs):
>         return self.f(*args, **kwargs)
>
> --
> Arnaud
>
>
Thanks for the corrections and the metaclass, Arnaud. (And thanks to you
too, Terry.) I might use it in my project.

> so what you are asking for is different from what Python 2.X provided.

Yes, I have been imprecise. So I'll correct my idea: I want Python 3.x to
tell me the class from which the unbound method was accessed. (It can be
done either on creation or or access, whatever seems better to you.) So I
propose this as a modification of Python.


Ram.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20100602/f77796ef/attachment.html>


More information about the Python-ideas mailing list