Can/should built-in functions get __get__?
One of the nice features of 3.0 is that differences between classes defined in C and Python (other than speed) are mostly erased or hidden from the view of a Python programmer. However, there are still sometimes surprising and quite visible differences between 'functions' written in C and Python. Can these be better unified also? In particular, built-in functions, in spite of of being labeled 'builtin_function_or_method', are not usable as methods because they lack the __get__ method needed to bind function to instance. [Q. Any reason to not shorten that to 'built-in function'?] So, as a c.l.p poster discovered, within a class statement, __hash__ = lambda x: id(x) # works, while the apparently cleaner __hash__ = id # raises TypeError: id() takes exactly one argument (0 given) [Irony: trivial lambda wrapping, lambda x: f(x) has been described here as useless and diseased, but is seems that casting 'built-in function' to 'function' is not so completely useless. ;-] In this case, __hash__ = object.__hash__ is available, as is object.__repr__, but this is not true in general for C functions. The difference between a C function and a C method wrapper is tantalizingly small:
i = set(dir(id)) h = set(dir(object.__hash__)) i-h {'__module__', '__self__'} h-i {'__objclass__', '__get__'}
Similarly, for
def f(): pass
ff = set(dir(f)) ff - i {'__defaults__', '__annotations__', '__kwdefaults__', '__globals__', '__closure__', '__dict__', '__code__', '__get__'}
the only un-obvious difference is __get__, So I cannot help but wonder: is this is essential? or could it be removed but has not yet? Could the object wrapper for C functions get a __get__ method so they become methods when accessed via a class just like Python functions do? Terry Jan Reedy
Terry Reedy wrote:
One of the nice features of 3.0 is that differences between classes defined in C and Python (other than speed) are mostly erased or hidden from the view of a Python programmer.
However, there are still sometimes surprising and quite visible differences between 'functions' written in C and Python. Can these be better unified also?
In particular, built-in functions, in spite of of being labeled 'builtin_function_or_method', are not usable as methods because they lack the __get__ method needed to bind function to instance.
Python is far too late in the release cycle to introduce a drastic change. The issues has been discussed about half a year ago and we decided against changing PyCFunction. But it was a good thing that you've raises your concern. I totally forgot about the new instancemethod type. My code is still in classobject.c but it's not exposed to Python level. IIRC the Pyrex/Cython guys are in need of such a feature. Patch: --- Python/bltinmodule.c (revision 66222) +++ Python/bltinmodule.c (working copy) @@ -2301,6 +2301,7 @@ SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); SETBUILTIN("int", &PyLong_Type); + SETBUILTIN("instancemethod", &PyInstanceMethod_Type); SETBUILTIN("list", &PyList_Type); SETBUILTIN("map", &PyMap_Type); SETBUILTIN("object", &PyBaseObject_Type); Result: $ ./python Python 3.0b3+ (py3k:66222M, Sep 5 2008, 02:24:22) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
class Example: ... id = instancemethod(id) ... example = Example() example.id() == id(example) True
Christian
Christian Heimes wrote:
Terry Reedy wrote:
One of the nice features of 3.0 is that differences between classes defined in C and Python (other than speed) are mostly erased or hidden from the view of a Python programmer.
However, there are still sometimes surprising and quite visible differences between 'functions' written in C and Python. Can these be better unified also?
In particular, built-in functions, in spite of of being labeled 'builtin_function_or_method', are not usable as methods because they lack the __get__ method needed to bind function to instance.
Python is far too late in the release cycle to introduce a drastic change.
Of course. I should have been clear that I was asking for 3.1.
The issues has been discussed about half a year ago and we decided against changing PyCFunction.
I did't remember that. Was it a permanent or provisional decision.
But it was a good thing that you've raises your concern. I totally forgot about the new instancemethod type. My code is still in classobject.c but it's not exposed to Python level. IIRC the Pyrex/Cython guys are in need of such a feature.
Patch:
--- Python/bltinmodule.c (revision 66222) +++ Python/bltinmodule.c (working copy) @@ -2301,6 +2301,7 @@ SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); SETBUILTIN("int", &PyLong_Type); + SETBUILTIN("instancemethod", &PyInstanceMethod_Type); SETBUILTIN("list", &PyList_Type); SETBUILTIN("map", &PyMap_Type); SETBUILTIN("object", &PyBaseObject_Type);
Result:
$ ./python Python 3.0b3+ (py3k:66222M, Sep 5 2008, 02:24:22) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
class Example: ... id = instancemethod(id) ... example = Example() example.id() == id(example) True
I consider that 2nd best but it will solve the problem once one is aware of it. I am thinking of suggesting a new paragraph for the Built-in Functions sections warning of differences between built-in functions and function instances. Terry
Terry Reedy wrote:
In particular, built-in functions, in spite of of being labeled 'builtin_function_or_method', are not usable as methods because they lack the __get__ method needed to bind function to instance.
They're not usable as Python-level instance methods, but they're definitely usable as methods, since they're used to implement methods for built-in types. I'm probably missing something, but I don't think there's a convenient method to get the internal function from a built-in type. However, you can find traces of them here and there:
"".upper.hello Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'builtin_function_or_method' object has no attribute 'hello' "".upper.__call__ <method-wrapper '__call__' of builtin_function_or_method object at 0x00C06260>
etc. </F>
participants (3)
-
Christian Heimes
-
Fredrik Lundh
-
Terry Reedy